cmake_dependent_option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY
"Install libc++experimental.a" ON
"LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF)
+cmake_dependent_option(LIBCXX_INSTALL_FILESYSTEM_LIBRARY
+ "Install libc++fs.a" ON
+ "LIBCXX_ENABLE_FILESYSTEM_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF)
+
if (FUCHSIA)
set(DEFAULT_ABI_VERSION 2)
else()
.. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL
- **Default**: ``LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY``
+ **Default**: ``ON``
+
+ Build filesystem as a standalone library libc++fs.a.
+
+.. option:: LIBCXX_INSTALL_FILESYSTEM_LIBRARY:BOOL
- Build filesystem as part of libc++experimental.a. This allows filesystem
- to be disabled without turning off the entire experimental library.
+ **Default**: ``LIBCXX_ENABLE_FILESYSTEM AND LIBCXX_INSTALL_LIBRARY``
+ Install libc++fs.a alongside libc++.
.. _ABI Library Specific Options:
$ export LD_LIBRARY_PATH=<libcxx-install-prefix>/lib
$ ./a.out # Searches for libc++ along LD_LIBRARY_PATH
+
+Using ``<filesystem>`` and libc++fs
+====================================
+
+Libc++ provides the implementation of the filesystem library in a separate
+library. Users of ``<filesystem>`` and ``<experimental/filesystem>`` are
+required to link ``-lc++fs``.
+
+.. note::
+ Prior to libc++ 7.0, users of ``<experimental/filesystem>`` were required
+ to link libc++experimental.
+
+.. warning::
+ The Filesystem library is still experimental in nature. As such normal
+ guarantees about ABI stability and backwards compatibility do not yet apply
+ to it. In the future, this restriction will be removed.
+
+
Using libc++experimental and ``<experimental/...>``
=====================================================
:ref:`Building Libc++ <build instructions>` and
:ref:`libc++experimental CMake Options <libc++experimental options>`.
+Note that as of libc++ 7.0 using the ``<experimental/filesystem>`` requires linking
+libc++fs instead of libc++experimental.
+
Also see the `Experimental Library Implementation Status <http://libcxx.llvm.org/ts1z_status.html>`__
page.
# endif
#endif
+#ifndef _LIBCPP_STD_VER
+# if __cplusplus <= 201103L
+# define _LIBCPP_STD_VER 11
+# elif __cplusplus <= 201402L
+# define _LIBCPP_STD_VER 14
+# elif __cplusplus <= 201703L
+# define _LIBCPP_STD_VER 17
+# else
+# define _LIBCPP_STD_VER 18 // current year, or date of c++2a ratification
+# endif
+#endif // _LIBCPP_STD_VER
+
#if defined(__ELF__)
# define _LIBCPP_OBJECT_FORMAT_ELF 1
#elif defined(__MACH__)
}
}
+#if _LIBCPP_STD_VER >= 17
+#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \
+ _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem {
+#else
+#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \
+ _LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem {
+#endif
+
+#define _LIBCPP_END_NAMESPACE_FILESYSTEM \
+ _LIBCPP_END_NAMESPACE_STD } }
+
+#define _VSTD_FS _VSTD::__fs::filesystem
+
#if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer)
#define _LIBCPP_HAS_NO_ASAN
#endif
#define _LIBCPP_WCTYPE_IS_MASK
#endif
-#ifndef _LIBCPP_STD_VER
-# if __cplusplus <= 201103L
-# define _LIBCPP_STD_VER 11
-# elif __cplusplus <= 201402L
-# define _LIBCPP_STD_VER 14
-# elif __cplusplus <= 201703L
-# define _LIBCPP_STD_VER 17
-# else
-# define _LIBCPP_STD_VER 18 // current year, or date of c++2a ratification
-# endif
-#endif // _LIBCPP_STD_VER
-
#if _LIBCPP_STD_VER > 11
# define _LIBCPP_DEPRECATED [[deprecated]]
#else
#define _VSTD_CORO _VSTD_EXPERIMENTAL::coroutines_v1
-#define _VSTD_FS ::std::experimental::filesystem::v1
-
#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD \
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace parallelism_v2 {
*/
#include <experimental/__config>
-#include <cstddef>
-#include <cstdlib>
-#include <chrono>
-#include <iterator>
-#include <iosfwd>
-#include <locale>
-#include <memory>
-#include <stack>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <iomanip> // for quoted
-#include <string_view>
-
-#include <__debug>
+#include <filesystem>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
-struct _FilesystemClock {
-#if !defined(_LIBCPP_HAS_NO_INT128)
- typedef __int128_t rep;
- typedef nano period;
-#else
- typedef long long rep;
- typedef nano period;
-#endif
-
- typedef chrono::duration<rep, period> duration;
- typedef chrono::time_point<_FilesystemClock> time_point;
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false;
-
- _LIBCPP_FUNC_VIS static time_point now() noexcept;
-
- _LIBCPP_INLINE_VISIBILITY
- static time_t to_time_t(const time_point& __t) noexcept {
- typedef chrono::duration<rep> __secs;
- return time_t(
- chrono::duration_cast<__secs>(__t.time_since_epoch()).count());
- }
-
- _LIBCPP_INLINE_VISIBILITY
- static time_point from_time_t(time_t __t) noexcept {
- typedef chrono::duration<rep> __secs;
- return time_point(__secs(__t));
- }
-};
-
-typedef chrono::time_point<_FilesystemClock> file_time_type;
-
-struct _LIBCPP_TYPE_VIS space_info
-{
- uintmax_t capacity;
- uintmax_t free;
- uintmax_t available;
-};
-
-enum class _LIBCPP_ENUM_VIS file_type : signed char
-{
- none = 0,
- not_found = -1,
- regular = 1,
- directory = 2,
- symlink = 3,
- block = 4,
- character = 5,
- fifo = 6,
- socket = 7,
- unknown = 8
-};
-
-enum class _LIBCPP_ENUM_VIS perms : unsigned
-{
- none = 0,
-
- owner_read = 0400,
- owner_write = 0200,
- owner_exec = 0100,
- owner_all = 0700,
-
- group_read = 040,
- group_write = 020,
- group_exec = 010,
- group_all = 070,
-
- others_read = 04,
- others_write = 02,
- others_exec = 01,
- others_all = 07,
-
- all = 0777,
-
- set_uid = 04000,
- set_gid = 02000,
- sticky_bit = 01000,
- mask = 07777,
- unknown = 0xFFFF,
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator&(perms _LHS, perms _RHS)
-{ return static_cast<perms>(static_cast<unsigned>(_LHS) & static_cast<unsigned>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator|(perms _LHS, perms _RHS)
-{ return static_cast<perms>(static_cast<unsigned>(_LHS) | static_cast<unsigned>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator^(perms _LHS, perms _RHS)
-{ return static_cast<perms>(static_cast<unsigned>(_LHS) ^ static_cast<unsigned>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perms operator~(perms _LHS)
-{ return static_cast<perms>(~static_cast<unsigned>(_LHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator&=(perms& _LHS, perms _RHS)
-{ return _LHS = _LHS & _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator|=(perms& _LHS, perms _RHS)
-{ return _LHS = _LHS | _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perms& operator^=(perms& _LHS, perms _RHS)
-{ return _LHS = _LHS ^ _RHS; }
-
-enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
- replace = 1,
- add = 2,
- remove = 4,
- nofollow = 8
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS)
-{ return static_cast<perm_options>(static_cast<unsigned>(_LHS) & static_cast<unsigned>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS)
-{ return static_cast<perm_options>(static_cast<unsigned>(_LHS) | static_cast<unsigned>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS)
-{ return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^ static_cast<unsigned>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr perm_options operator~(perm_options _LHS)
-{ return static_cast<perm_options>(~static_cast<unsigned>(_LHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS)
-{ return _LHS = _LHS & _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS)
-{ return _LHS = _LHS | _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS)
-{ return _LHS = _LHS ^ _RHS; }
-
-enum class _LIBCPP_ENUM_VIS copy_options : unsigned short
-{
- none = 0,
- skip_existing = 1,
- overwrite_existing = 2,
- update_existing = 4,
- recursive = 8,
- copy_symlinks = 16,
- skip_symlinks = 32,
- directories_only = 64,
- create_symlinks = 128,
- create_hard_links = 256,
- __in_recursive_copy = 512,
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS)
-{ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) & static_cast<unsigned short>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS)
-{ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) | static_cast<unsigned short>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS)
-{ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^ static_cast<unsigned short>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr copy_options operator~(copy_options _LHS)
-{ return static_cast<copy_options>(~static_cast<unsigned short>(_LHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS)
-{ return _LHS = _LHS & _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS)
-{ return _LHS = _LHS | _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS)
-{ return _LHS = _LHS ^ _RHS; }
-
-
-enum class _LIBCPP_ENUM_VIS directory_options : unsigned char
-{
- none = 0,
- follow_directory_symlink = 1,
- skip_permission_denied = 2
-};
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator&(directory_options _LHS, directory_options _RHS)
-{ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) & static_cast<unsigned char>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator|(directory_options _LHS, directory_options _RHS)
-{ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) | static_cast<unsigned char>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator^(directory_options _LHS, directory_options _RHS)
-{ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^ static_cast<unsigned char>(_RHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline constexpr directory_options operator~(directory_options _LHS)
-{ return static_cast<directory_options>(~static_cast<unsigned char>(_LHS)); }
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator&=(directory_options& _LHS, directory_options _RHS)
-{ return _LHS = _LHS & _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator|=(directory_options& _LHS, directory_options _RHS)
-{ return _LHS = _LHS | _RHS; }
-
-_LIBCPP_INLINE_VISIBILITY
-inline directory_options& operator^=(directory_options& _LHS, directory_options _RHS)
-{ return _LHS = _LHS ^ _RHS; }
-
-
-class _LIBCPP_TYPE_VIS file_status
-{
-public:
- // constructors
- _LIBCPP_INLINE_VISIBILITY
- file_status() noexcept : file_status(file_type::none) {}
- _LIBCPP_INLINE_VISIBILITY
- explicit file_status(file_type __ft,
- perms __prms = perms::unknown) noexcept
- : __ft_(__ft), __prms_(__prms)
- {}
-
- file_status(const file_status&) noexcept = default;
- file_status(file_status&&) noexcept = default;
-
- _LIBCPP_INLINE_VISIBILITY
- ~file_status() {}
-
- file_status& operator=(const file_status&) noexcept = default;
- file_status& operator=(file_status&&) noexcept = default;
-
- // observers
- _LIBCPP_INLINE_VISIBILITY
- file_type type() const noexcept {
- return __ft_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- perms permissions() const noexcept {
- return __prms_;
- }
-
- // modifiers
- _LIBCPP_INLINE_VISIBILITY
- void type(file_type __ft) noexcept {
- __ft_ = __ft;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void permissions(perms __p) noexcept {
- __prms_ = __p;
- }
-private:
- file_type __ft_;
- perms __prms_;
-};
-
-class _LIBCPP_TYPE_VIS directory_entry;
-
-template <class _Tp> struct __can_convert_char {
- static const bool value = false;
-};
-template <class _Tp> struct __can_convert_char<const _Tp>
- : public __can_convert_char<_Tp> {
-};
-template <> struct __can_convert_char<char> {
- static const bool value = true;
- using __char_type = char;
-};
-template <> struct __can_convert_char<wchar_t> {
- static const bool value = true;
- using __char_type = wchar_t;
-};
-template <> struct __can_convert_char<char16_t> {
- static const bool value = true;
- using __char_type = char16_t;
-};
-template <> struct __can_convert_char<char32_t> {
- static const bool value = true;
- using __char_type = char32_t;
-};
-
-template <class _ECharT>
-typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
-__is_separator(_ECharT __e) {
- return __e == _ECharT('/');
-};
-
-struct _NullSentinal {};
-
-template <class _Tp>
-using _Void = void;
-
-template <class _Tp, class = void>
-struct __is_pathable_string : public false_type {};
-
-template <class _ECharT, class _Traits, class _Alloc>
-struct __is_pathable_string<basic_string<_ECharT, _Traits, _Alloc>,
- _Void<typename __can_convert_char<_ECharT>::__char_type>>
-: public __can_convert_char<_ECharT>
-{
- using _Str = basic_string<_ECharT, _Traits, _Alloc>;
- using _Base = __can_convert_char<_ECharT>;
- static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
- static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
- static _ECharT __first_or_null(_Str const& __s) {
- return __s.empty() ? _ECharT{} : __s[0];
- }
-};
-
-
-template <class _ECharT, class _Traits>
-struct __is_pathable_string<basic_string_view<_ECharT, _Traits>,
- _Void<typename __can_convert_char<_ECharT>::__char_type>>
-: public __can_convert_char<_ECharT>
-{
- using _Str = basic_string_view<_ECharT, _Traits>;
- using _Base = __can_convert_char<_ECharT>;
- static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
- static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); }
- static _ECharT __first_or_null(_Str const& __s) {
- return __s.empty() ? _ECharT{} : __s[0];
- }
-};
-
-template <class _Source,
- class _DS = typename decay<_Source>::type,
- class _UnqualPtrType = typename remove_const<
- typename remove_pointer<_DS>::type>::type,
- bool _IsCharPtr = is_pointer<_DS>::value &&
- __can_convert_char<_UnqualPtrType>::value
- >
-struct __is_pathable_char_array : false_type {};
-
-template <class _Source, class _ECharT, class _UPtr>
-struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
- : __can_convert_char<typename remove_const<_ECharT>::type>
-{
- using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
-
- static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
- static _ECharT const* __range_end(const _ECharT* __b)
- {
- using _Iter = const _ECharT*;
- const _ECharT __sentinal = _ECharT{};
- _Iter __e = __b;
- for (; *__e != __sentinal; ++__e)
- ;
- return __e;
- }
-
- static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
-};
-
-template <class _Iter, bool _IsIt = __is_input_iterator<_Iter>::value, class = void>
-struct __is_pathable_iter : false_type {};
-
-template <class _Iter>
-struct __is_pathable_iter<_Iter, true,
- _Void<typename __can_convert_char<typename iterator_traits<_Iter>::value_type>::__char_type>>
- : __can_convert_char<typename iterator_traits<_Iter>::value_type>
-{
- using _ECharT = typename iterator_traits<_Iter>::value_type;
- using _Base = __can_convert_char<_ECharT>;
-
- static _Iter __range_begin(_Iter __b) { return __b; }
- static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; }
-
- static _ECharT __first_or_null(_Iter __b) { return *__b; }
-};
-
-template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
- bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
- bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value
- >
-struct __is_pathable : false_type {
- static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
-};
-
-template <class _Tp>
-struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
-
-
-template <class _Tp>
-struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {};
-
-
-template <class _Tp>
-struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
-
-
-template <class _ECharT>
-struct _PathCVT {
- static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible");
-
- typedef __narrow_to_utf8<sizeof(_ECharT)*__CHAR_BIT__> _Narrower;
-
- static void __append_range(string& __dest, _ECharT const* __b, _ECharT const* __e) {
- _Narrower()(back_inserter(__dest), __b, __e);
- }
-
- template <class _Iter>
- static void __append_range(string& __dest, _Iter __b, _Iter __e) {
- static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
- if (__b == __e) return;
- basic_string<_ECharT> __tmp(__b, __e);
- _Narrower()(back_inserter(__dest), __tmp.data(),
- __tmp.data() + __tmp.length());
- }
-
- template <class _Iter>
- static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
- static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
- const _ECharT __sentinal = _ECharT{};
- if (*__b == __sentinal) return;
- basic_string<_ECharT> __tmp;
- for (; *__b != __sentinal; ++__b)
- __tmp.push_back(*__b);
- _Narrower()(back_inserter(__dest), __tmp.data(),
- __tmp.data() + __tmp.length());
- }
-
- template <class _Source>
- static void __append_source(string& __dest, _Source const& __s)
- {
- using _Traits = __is_pathable<_Source>;
- __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s));
- }
-};
-
-template <>
-struct _PathCVT<char> {
-
- template <class _Iter>
- static typename enable_if<
- __is_exactly_input_iterator<_Iter>::value
- >::type __append_range(string& __dest, _Iter __b, _Iter __e) {
- for (; __b != __e; ++__b)
- __dest.push_back(*__b);
- }
-
- template <class _Iter>
- static typename enable_if<
- __is_forward_iterator<_Iter>::value
- >::type __append_range(string& __dest, _Iter __b, _Iter __e) {
- __dest.__append_forward_unsafe(__b, __e);
- }
-
- template <class _Iter>
- static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
- const char __sentinal = char{};
- for (; *__b != __sentinal; ++__b)
- __dest.push_back(*__b);
- }
-
- template <class _Source>
- static void __append_source(string& __dest, _Source const& __s)
- {
- using _Traits = __is_pathable<_Source>;
- __append_range(__dest, _Traits::__range_begin(__s),
- _Traits::__range_end(__s));
- }
-};
-
-
-class _LIBCPP_TYPE_VIS path
-{
- template <class _SourceOrIter, class _Tp = path&>
- using _EnableIfPathable = typename
- enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
-
- template <class _Tp>
- using _SourceChar = typename __is_pathable<_Tp>::__char_type;
-
- template <class _Tp>
- using _SourceCVT = _PathCVT<_SourceChar<_Tp>>;
-
-public:
- typedef char value_type;
- typedef basic_string<value_type> string_type;
- typedef _VSTD::string_view __string_view;
- static constexpr value_type preferred_separator = '/';
-
- enum class _LIBCPP_ENUM_VIS format : unsigned char {
- auto_format,
- native_format,
- generic_format
- };
-
- // constructors and destructor
- _LIBCPP_INLINE_VISIBILITY path() noexcept {}
- _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
- _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept : __pn_(_VSTD::move(__p.__pn_)) {}
-
- _LIBCPP_INLINE_VISIBILITY
- path(string_type&& __s, format = format::auto_format) noexcept
- : __pn_(_VSTD::move(__s)) {}
-
- template <
- class _Source,
- class = _EnableIfPathable<_Source, void>
- >
- path(const _Source& __src, format = format::auto_format) {
- _SourceCVT<_Source>::__append_source(__pn_, __src);
- }
-
- template <class _InputIt>
- path(_InputIt __first, _InputIt __last, format = format::auto_format) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
- }
-
- // TODO Implement locale conversions.
- template <class _Source,
- class = _EnableIfPathable<_Source, void>
- >
- path(const _Source& __src, const locale& __loc,
- format = format::auto_format);
- template <class _InputIt>
- path(_InputIt __first, _InputIt _last, const locale& __loc,
- format = format::auto_format);
-
- _LIBCPP_INLINE_VISIBILITY
- ~path() = default;
-
- // assignments
- _LIBCPP_INLINE_VISIBILITY
- path& operator=(const path& __p) {
- __pn_ = __p.__pn_;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator=(path&& __p) noexcept {
- __pn_ = _VSTD::move(__p.__pn_);
- return *this;
- }
-
- template <class = void>
- _LIBCPP_INLINE_VISIBILITY
- path& operator=(string_type&& __s) noexcept {
- __pn_ = _VSTD::move(__s);
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& assign(string_type&& __s) noexcept {
- __pn_ = _VSTD::move(__s);
- return *this;
- }
-
- template <class _Source>
- _LIBCPP_INLINE_VISIBILITY
- _EnableIfPathable<_Source>
- operator=(const _Source& __src)
- { return this->assign(__src); }
-
-
- template <class _Source>
- _EnableIfPathable<_Source>
- assign(const _Source& __src) {
- __pn_.clear();
- _SourceCVT<_Source>::__append_source(__pn_, __src);
- return *this;
- }
-
- template <class _InputIt>
- path& assign(_InputIt __first, _InputIt __last) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- __pn_.clear();
- _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
- return *this;
- }
-
-private:
- template <class _ECharT>
- static bool __source_is_absolute(_ECharT __first_or_null) {
- return __is_separator(__first_or_null);
- }
-
-public:
- // appends
- path& operator/=(const path& __p) {
- 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>
- operator/=(const _Source& __src) {
- return this->append(__src);
- }
-
- template <class _Source>
- _EnableIfPathable<_Source>
- append(const _Source& __src) {
- using _Traits = __is_pathable<_Source>;
- using _CVT = _PathCVT<_SourceChar<_Source>>;
- 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;
- }
-
- template <class _InputIt>
- path& append(_InputIt __first, _InputIt __last) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
- using _CVT = _PathCVT<_ItVal>;
- if (__first != __last && __source_is_absolute(*__first))
- __pn_.clear();
- else if (has_filename())
- __pn_ += preferred_separator;
- _CVT::__append_range(__pn_, __first, __last);
- return *this;
- }
-
- // concatenation
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(const path& __x) {
- __pn_ += __x.__pn_;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(const string_type& __x) {
- __pn_ += __x;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(__string_view __x) {
- __pn_ += __x;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(const value_type* __x) {
- __pn_ += __x;
- return *this;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- path& operator+=(value_type __x) {
- __pn_ += __x;
- return *this;
- }
-
- template <class _ECharT>
- typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
- operator+=(_ECharT __x)
- {
- basic_string<_ECharT> __tmp;
- __tmp += __x;
- _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
- return *this;
- }
-
- template <class _Source>
- _EnableIfPathable<_Source>
- operator+=(const _Source& __x) {
- return this->concat(__x);
- }
-
- template <class _Source>
- _EnableIfPathable<_Source>
- concat(const _Source& __x) {
- _SourceCVT<_Source>::__append_source(__pn_, __x);
- return *this;
- }
-
- template <class _InputIt>
- path& concat(_InputIt __first, _InputIt __last) {
- typedef typename iterator_traits<_InputIt>::value_type _ItVal;
- _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
- return *this;
- }
-
- // modifiers
- _LIBCPP_INLINE_VISIBILITY
- void clear() noexcept {
- __pn_.clear();
- }
-
- path& make_preferred() { return *this; }
-
- _LIBCPP_INLINE_VISIBILITY
- path& remove_filename() {
- auto __fname = __filename();
- if (!__fname.empty())
- __pn_.erase(__fname.data() - __pn_.data());
- return *this;
- }
-
- path& replace_filename(const path& __replacement) {
- remove_filename();
- return (*this /= __replacement);
- }
-
- path& replace_extension(const path& __replacement = path());
-
- _LIBCPP_INLINE_VISIBILITY
- void swap(path& __rhs) noexcept {
- __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 {
- return __pn_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- const value_type* c_str() const noexcept { return __pn_.c_str(); }
-
- _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
-
- template <class _ECharT, class _Traits = char_traits<_ECharT>,
- class _Allocator = allocator<_ECharT> >
- basic_string<_ECharT, _Traits, _Allocator>
- string(const _Allocator& __a = _Allocator()) const {
- using _CVT = __widen_from_utf8<sizeof(_ECharT)*__CHAR_BIT__>;
- using _Str = basic_string<_ECharT, _Traits, _Allocator>;
- _Str __s(__a);
- __s.reserve(__pn_.size());
- _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
- return __s;
- }
-
- _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
- _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const { return string<wchar_t>(); }
- _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
- _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const { return string<char16_t>(); }
- _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const { return string<char32_t>(); }
-
- // generic format observers
- template <class _ECharT, class _Traits = char_traits<_ECharT>,
- class _Allocator = allocator<_ECharT>
- >
- basic_string<_ECharT, _Traits, _Allocator>
- generic_string(const _Allocator& __a = _Allocator()) const {
- return string<_ECharT, _Traits, _Allocator>(__a);
- }
-
- std::string generic_string() const { return __pn_; }
- std::wstring generic_wstring() const { return string<wchar_t>(); }
- std::string generic_u8string() const { return __pn_; }
- std::u16string generic_u16string() const { return string<char16_t>(); }
- std::u32string generic_u32string() const { return string<char32_t>(); }
-
-private:
- int __compare(__string_view) const;
- __string_view __root_name() const;
- __string_view __root_directory() const;
- __string_view __root_path_raw() const;
- __string_view __relative_path() const;
- __string_view __parent_path() const;
- __string_view __filename() const;
- __string_view __stem() const;
- __string_view __extension() const;
-
-public:
- // compare
- _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept { return __compare(__p.__pn_);}
- _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { return __compare(__s); }
- _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const { return __compare(__s); }
- _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const { return __compare(__s); }
-
- // decomposition
- _LIBCPP_INLINE_VISIBILITY path root_name() const { return string_type(__root_name()); }
- _LIBCPP_INLINE_VISIBILITY path root_directory() const { return string_type(__root_directory()); }
- _LIBCPP_INLINE_VISIBILITY path root_path() const { return root_name().append(string_type(__root_directory())); }
- _LIBCPP_INLINE_VISIBILITY path relative_path() const { return string_type(__relative_path()); }
- _LIBCPP_INLINE_VISIBILITY path parent_path() const { return string_type(__parent_path()); }
- _LIBCPP_INLINE_VISIBILITY path filename() const { return string_type(__filename()); }
- _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem());}
- _LIBCPP_INLINE_VISIBILITY path extension() const { return string_type(__extension()); }
-
- // query
- _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
- bool empty() const noexcept { return __pn_.empty(); }
-
- _LIBCPP_INLINE_VISIBILITY bool has_root_name() const { return !__root_name().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const { return !__root_directory().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_root_path() const { return !__root_path_raw().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const { return !__relative_path().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const { return !__parent_path().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_filename() const { return !__filename().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
- _LIBCPP_INLINE_VISIBILITY bool has_extension() const { return !__extension().empty(); }
-
- _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;
-
- iterator begin() const;
- iterator end() const;
-
-
- template <class _CharT, class _Traits>
- _LIBCPP_INLINE_VISIBILITY
- friend typename enable_if<is_same<_CharT, char>::value &&
- is_same<_Traits, char_traits<char>>::value,
- basic_ostream<_CharT, _Traits>&
- >::type
- operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
- __os << std::__quoted(__p.native());
- return __os;
- }
-
- template <class _CharT, class _Traits>
- _LIBCPP_INLINE_VISIBILITY
- friend typename enable_if<!is_same<_CharT, char>::value ||
- !is_same<_Traits, char_traits<char>>::value,
- basic_ostream<_CharT, _Traits>&
- >::type
- operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
- __os << std::__quoted(__p.string<_CharT, _Traits>());
- return __os;
- }
-
- template <class _CharT, class _Traits>
- _LIBCPP_INLINE_VISIBILITY
- friend basic_istream<_CharT, _Traits>&
- operator>>(basic_istream<_CharT, _Traits>& __is, path& __p)
- {
- basic_string<_CharT, _Traits> __tmp;
- __is >> __quoted(__tmp);
- __p = __tmp;
- return __is;
- }
-
-private:
- inline _LIBCPP_INLINE_VISIBILITY
- path& __assign_view(__string_view const& __s) noexcept { __pn_ = string_type(__s); return *this; }
- string_type __pn_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY
-void swap(path& __lhs, path& __rhs) noexcept {
- __lhs.swap(__rhs);
-}
-
-_LIBCPP_FUNC_VIS
-size_t hash_value(const path& __p) noexcept;
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator==(const path& __lhs, const path& __rhs) noexcept
-{ return __lhs.compare(__rhs) == 0; }
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator!=(const path& __lhs, const path& __rhs) noexcept
-{ return __lhs.compare(__rhs) != 0; }
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator<(const path& __lhs, const path& __rhs) noexcept
-{ return __lhs.compare(__rhs) < 0; }
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator<=(const path& __lhs, const path& __rhs) noexcept
-{ return __lhs.compare(__rhs) <= 0; }
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator>(const path& __lhs, const path& __rhs) noexcept
-{ return __lhs.compare(__rhs) > 0; }
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator>=(const path& __lhs, const path& __rhs) noexcept
-{ return __lhs.compare(__rhs) >= 0; }
-
-inline _LIBCPP_INLINE_VISIBILITY
-path operator/(const path& __lhs, const path& __rhs) {
- path __result(__lhs);
- __result /= __rhs;
- return __result;
-}
-
-template <class _Source>
-_LIBCPP_INLINE_VISIBILITY
-typename enable_if<__is_pathable<_Source>::value, path>::type
-u8path(const _Source& __s){
- static_assert(is_same<typename __is_pathable<_Source>::__char_type, char>::value,
- "u8path(Source const&) requires Source have a character type of type 'char'");
- return path(__s);
-}
-
-template <class _InputIt>
-_LIBCPP_INLINE_VISIBILITY
-typename enable_if<__is_pathable<_InputIt>::value, path>::type
-u8path(_InputIt __f, _InputIt __l) {
- static_assert(is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
- "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
- return path(__f, __l);
-}
-
-class _LIBCPP_TYPE_VIS path::iterator
-{
-public:
- enum _ParserState : unsigned char {
- _Singular,
- _BeforeBegin,
- _InRootName,
- _InRootDir,
- _InFilenames,
- _InTrailingSep,
- _AtEnd
- };
-
-public:
- typedef bidirectional_iterator_tag iterator_category;
-
- typedef path value_type;
- typedef std::ptrdiff_t difference_type;
- typedef const path* pointer;
- typedef const path& reference;
-
- typedef void __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
-
-public:
- _LIBCPP_INLINE_VISIBILITY
- iterator() : __stashed_elem_(), __path_ptr_(nullptr),
- __entry_(), __state_(_Singular) {}
-
- iterator(const iterator&) = default;
- ~iterator() = default;
-
- iterator& operator=(const iterator&) = default;
-
- _LIBCPP_INLINE_VISIBILITY
- reference operator*() const {
- return __stashed_elem_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- pointer operator->() const {
- return &__stashed_elem_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator& operator++() {
- _LIBCPP_ASSERT(__state_ != _Singular,
- "attempting to increment a singular iterator");
- _LIBCPP_ASSERT(__state_ != _AtEnd,
- "attempting to increment the end iterator");
- return __increment();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator operator++(int) {
- iterator __it(*this);
- this->operator++();
- return __it;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator& operator--() {
- _LIBCPP_ASSERT(__state_ != _Singular,
- "attempting to decrement a singular iterator");
- _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
- "attempting to decrement the begin iterator");
- return __decrement();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- iterator operator--(int) {
- iterator __it(*this);
- this->operator--();
- return __it;
- }
-
-private:
- friend class path;
-
- inline _LIBCPP_INLINE_VISIBILITY
- friend bool operator==(const iterator&, const iterator&);
-
- iterator& __increment();
- iterator& __decrement();
-
- path __stashed_elem_;
- const path* __path_ptr_;
- path::__string_view __entry_;
- _ParserState __state_;
-};
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator==(const path::iterator& __lhs, const path::iterator& __rhs) {
- return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
- __lhs.__entry_.data() == __rhs.__entry_.data();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator!=(const path::iterator& __lhs, const path::iterator& __rhs) {
- return !(__lhs == __rhs);
-}
-
-class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error
-{
-public:
- _LIBCPP_INLINE_VISIBILITY
- filesystem_error(const string& __what, error_code __ec)
- : system_error(__ec, __what),
- __storage_(make_shared<_Storage>(path(), path())) {
- __create_what(0);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- filesystem_error(const string& __what, const path& __p1, error_code __ec)
- : system_error(__ec, __what),
- __storage_(make_shared<_Storage>(__p1, path())) {
- __create_what(1);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- filesystem_error(const string& __what, const path& __p1, const path& __p2,
- error_code __ec)
- : system_error(__ec, __what),
- __storage_(make_shared<_Storage>(__p1, __p2)) {
- __create_what(2);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- const path& path1() const noexcept { return __storage_->__p1_; }
-
- _LIBCPP_INLINE_VISIBILITY
- const path& path2() const noexcept { return __storage_->__p2_; }
-
- ~filesystem_error() override; // key function
-
- _LIBCPP_INLINE_VISIBILITY
- const char* what() const noexcept override {
- return __storage_->__what_.c_str();
- }
-
- _LIBCPP_FUNC_VIS
- void __create_what(int __num_paths);
-
- private:
- struct _Storage {
- _LIBCPP_INLINE_VISIBILITY
- _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
-
- path __p1_;
- path __p2_;
- string __what_;
- };
- shared_ptr<_Storage> __storage_;
-};
-
-template <class... _Args>
-_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
-#ifndef _LIBCPP_NO_EXCEPTIONS
-void __throw_filesystem_error(_Args && ...__args)
-{
- throw filesystem_error(std::forward<_Args>(__args)...);
-}
-#else
-void __throw_filesystem_error(_Args&&...)
-{
- _VSTD::abort();
-}
-#endif
-
-// operational functions
-
-_LIBCPP_FUNC_VIS
-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);
-_LIBCPP_FUNC_VIS
-bool __copy_file(const path& __from, const path& __to, copy_options __opt,
- error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
- error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directories(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directory(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-bool __create_directory(const path& p, const path & attributes,
- error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __create_directory_symlink(const path& __to, const path& __new_symlink,
- error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __create_hard_link(const path& __to, const path& __new_hard_link,
- error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __create_symlink(const path& __to, const path& __new_symlink,
- error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-path __current_path(error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __current_path(const path&, error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-bool __equivalent(const path&, const path&, error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __file_size(const path&, error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __hard_link_count(const path&, error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-bool __fs_is_empty(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-file_time_type __last_write_time(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __last_write_time(const path& p, file_time_type new_time,
- error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __permissions(const path&, perms, perm_options, error_code* = nullptr);
-_LIBCPP_FUNC_VIS
-path __read_symlink(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-bool __remove(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-uintmax_t __remove_all(const path& p, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __rename(const path& from, const path& to, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-void __resize_file(const path& p, uintmax_t size, error_code *ec=nullptr);
-_LIBCPP_FUNC_VIS
-space_info __space(const path&, error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-file_status __status(const path&, error_code *__ec=nullptr);
-_LIBCPP_FUNC_VIS
-file_status __symlink_status(const path&, error_code *__ec=nullptr);
-_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() {
- return __current_path();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path current_path(error_code& __ec) {
- return __current_path(&__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void current_path(const path& __p) {
- __current_path(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void current_path(const path& __p, error_code& __ec) noexcept {
- __current_path(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path absolute(const path& __p) {
- return __absolute(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path absolute(const path& __p, error_code &__ec) {
- return __absolute(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path canonical(const path& __p) {
- return __canonical(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path canonical(const path& __p, error_code& __ec) {
- return __canonical(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void copy(const path& __from, const path& __to) {
- __copy(__from, __to, copy_options::none);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void copy(const path& __from, const path& __to, error_code& __ec) {
- __copy(__from, __to, copy_options::none, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void copy(const path& __from, const path& __to, copy_options __opt) {
- __copy(__from, __to, __opt);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void copy(const path& __from, const path& __to,
- copy_options __opt, error_code& __ec) {
- __copy(__from, __to, __opt, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool copy_file(const path& __from, const path& __to) {
- return __copy_file(__from, __to, copy_options::none);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool copy_file(const path& __from, const path& __to, error_code& __ec) {
- return __copy_file(__from, __to, copy_options::none, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool copy_file(const path& __from, const path& __to, copy_options __opt) {
- return __copy_file(__from, __to, __opt);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool copy_file(const path& __from, const path& __to,
- copy_options __opt, error_code& __ec){
- return __copy_file(__from, __to, __opt, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void copy_symlink(const path& __existing, const path& __new) {
- __copy_symlink(__existing, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
- __copy_symlink(__ext, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool create_directories(const path& __p) {
- return __create_directories(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool create_directories(const path& __p, error_code& __ec) {
- return __create_directories(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool create_directory(const path& __p) {
- return __create_directory(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool create_directory(const path& __p, error_code& __ec) noexcept {
- return __create_directory(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool create_directory(const path& __p, const path& __attrs) {
- return __create_directory(__p, __attrs);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool create_directory(const path& __p, const path& __attrs, error_code& __ec) noexcept {
- return __create_directory(__p, __attrs, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void create_directory_symlink(const path& __to, const path& __new) {
- __create_directory_symlink(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void create_directory_symlink(const path& __to, const path& __new,
- error_code& __ec) noexcept {
- __create_directory_symlink(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void create_hard_link(const path& __to, const path& __new) {
- __create_hard_link(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void create_hard_link(const path& __to, const path& __new, error_code& __ec) noexcept {
- __create_hard_link(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void create_symlink(const path& __to, const path& __new) {
- __create_symlink(__to, __new);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void create_symlink(const path& __to, const path& __new,
- error_code& __ec) noexcept {
- return __create_symlink(__to, __new, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool status_known(file_status __s) noexcept {
- return __s.type() != file_type::none;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool exists(file_status __s) noexcept {
- return status_known(__s) && __s.type() != file_type::not_found;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool exists(const path& __p) {
- return exists(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool exists(const path& __p, error_code& __ec) noexcept {
- auto __s = __status(__p, &__ec);
- if (status_known(__s)) __ec.clear();
- return exists(__s);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool equivalent(const path& __p1, const path& __p2) {
- return __equivalent(__p1, __p2);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
- return __equivalent(__p1, __p2, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-uintmax_t file_size(const path& __p) {
- return __file_size(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-uintmax_t file_size(const path& __p, error_code& __ec) noexcept {
- return __file_size(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-uintmax_t hard_link_count(const path& __p) {
- return __hard_link_count(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept {
- return __hard_link_count(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_block_file(file_status __s) noexcept {
- return __s.type() == file_type::block;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_block_file(const path& __p) {
- return is_block_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_block_file(const path& __p, error_code& __ec) noexcept {
- return is_block_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_character_file(file_status __s) noexcept {
- return __s.type() == file_type::character;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_character_file(const path& __p) {
- return is_character_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_character_file(const path& __p, error_code& __ec) noexcept {
- return is_character_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_directory(file_status __s) noexcept {
- return __s.type() == file_type::directory;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_directory(const path& __p) {
- return is_directory(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_directory(const path& __p, error_code& __ec) noexcept {
- return is_directory(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_empty(const path& __p) {
- return __fs_is_empty(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_empty(const path& __p, error_code& __ec) {
- return __fs_is_empty(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_fifo(file_status __s) noexcept {
- return __s.type() == file_type::fifo;
-}
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_fifo(const path& __p) {
- return is_fifo(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_fifo(const path& __p, error_code& __ec) noexcept {
- return is_fifo(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_regular_file(file_status __s) noexcept {
- return __s.type() == file_type::regular;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_regular_file(const path& __p) {
- return is_regular_file(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_regular_file(const path& __p, error_code& __ec) noexcept {
- return is_regular_file(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_socket(file_status __s) noexcept {
- return __s.type() == file_type::socket;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_socket(const path& __p) {
- return is_socket(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_socket(const path& __p, error_code& __ec) noexcept {
- return is_socket(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_symlink(file_status __s) noexcept {
- return __s.type() == file_type::symlink;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_symlink(const path& __p) {
- return is_symlink(__symlink_status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_symlink(const path& __p, error_code& __ec) noexcept {
- return is_symlink(__symlink_status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_other(file_status __s) noexcept {
- return exists(__s)
- && !is_regular_file(__s) && !is_directory(__s) && !is_symlink(__s);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_other(const path& __p) {
- return is_other(__status(__p));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool is_other(const path& __p, error_code& __ec) noexcept {
- return is_other(__status(__p, &__ec));
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-file_time_type last_write_time(const path& __p) {
- return __last_write_time(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-file_time_type last_write_time(const path& __p, error_code& __ec) noexcept {
- return __last_write_time(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void last_write_time(const path& __p, file_time_type __t) {
- __last_write_time(__p, __t);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept {
- __last_write_time(__p, __t, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void permissions(const path& __p, perms __prms,
- perm_options __opts = perm_options::replace) {
- __permissions(__p, __prms, __opts);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void permissions(const path& __p, perms __prms, error_code& __ec) noexcept {
- __permissions(__p, __prms, perm_options::replace, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void permissions(const path& __p, perms __prms, perm_options __opts,
- error_code& __ec) {
- __permissions(__p, __prms, __opts, &__ec);
-}
-
-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);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-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);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool remove(const path& __p, error_code& __ec) noexcept {
- return __remove(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-uintmax_t remove_all(const path& __p) {
- return __remove_all(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-uintmax_t remove_all(const path& __p, error_code& __ec) {
- return __remove_all(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void rename(const path& __from, const path& __to) {
- return __rename(__from, __to);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void rename(const path& __from, const path& __to, error_code& __ec) noexcept {
- return __rename(__from, __to, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void resize_file(const path& __p, uintmax_t __ns) {
- return __resize_file(__p, __ns);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
- return __resize_file(__p, __ns, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-space_info space(const path& __p) {
- return __space(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-space_info space(const path& __p, error_code& __ec) noexcept {
- return __space(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-file_status status(const path& __p) {
- return __status(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-file_status status(const path& __p, error_code& __ec) noexcept {
- return __status(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-file_status symlink_status(const path& __p) {
- return __symlink_status(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-file_status symlink_status(const path& __p, error_code& __ec) noexcept {
- return __symlink_status(__p, &__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path temp_directory_path() {
- return __temp_directory_path();
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path temp_directory_path(error_code& __ec) {
- return __temp_directory_path(&__ec);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path weakly_canonical(path const& __p) {
- return __weakly_canonical(__p);
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-path weakly_canonical(path const& __p, error_code& __ec) {
- return __weakly_canonical(__p, &__ec);
-}
-
-
-class directory_iterator;
-class recursive_directory_iterator;
-class __dir_stream;
-
-class directory_entry
-{
- typedef _VSTD_FS::path _Path;
-
-public:
- // constructors and destructors
- directory_entry() noexcept = default;
- directory_entry(directory_entry const&) = default;
- directory_entry(directory_entry&&) noexcept = default;
-
- _LIBCPP_INLINE_VISIBILITY
- explicit directory_entry(_Path const& __p) : __p_(__p) {
- error_code __ec;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- directory_entry(_Path const& __p, error_code &__ec) : __p_(__p) {
- __refresh(&__ec);
- }
-
- ~directory_entry() {}
-
- directory_entry& operator=(directory_entry const&) = default;
- directory_entry& operator=(directory_entry&&) noexcept = default;
-
- _LIBCPP_INLINE_VISIBILITY
- void assign(_Path const& __p) {
- __p_ = __p;
- error_code __ec;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void assign(_Path const& __p, error_code& __ec) {
- __p_ = __p;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void replace_filename(_Path const& __p) {
- __p_.replace_filename(__p);
- error_code __ec;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void replace_filename(_Path const& __p, error_code &__ec) {
- __p_ = __p_.parent_path() / __p;
- __refresh(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void refresh() {
- __refresh();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
-
- _LIBCPP_INLINE_VISIBILITY
- _Path const& path() const noexcept {
- return __p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- operator const _Path&() const noexcept {
- return __p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool exists() const {
- return _VSTD_FS::exists(file_status{__get_ft()});
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool exists(error_code& __ec) const noexcept {
- return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_block_file() const {
- return __get_ft() == file_type::block;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_block_file(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::block;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_character_file() const {
- return __get_ft() == file_type::character;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_character_file(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::character;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_directory() const {
- return __get_ft() == file_type::directory;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_directory(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::directory;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_fifo() const {
- return __get_ft() == file_type::fifo;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_fifo(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::fifo;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_other() const {
- return _VSTD_FS::is_other(file_status{__get_ft()});
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_other(error_code& __ec) const noexcept {
- return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_regular_file() const {
- return __get_ft() == file_type::regular;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_regular_file(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::regular;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_socket() const {
- return __get_ft() == file_type::socket;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_socket(error_code& __ec) const noexcept {
- return __get_ft(&__ec) == file_type::socket;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_symlink() const {
- return __get_sym_ft() == file_type::symlink;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool is_symlink(error_code& __ec) const noexcept {
- return __get_sym_ft(&__ec) == file_type::symlink;
- }
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t file_size() const {
- return __get_size();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t file_size(error_code& __ec) const noexcept {
- return __get_size(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t hard_link_count() const {
- return __get_nlink();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t hard_link_count(error_code& __ec) const noexcept {
- return __get_nlink(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_time_type last_write_time() const {
- return __get_write_time();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_time_type last_write_time(error_code& __ec) const noexcept {
- return __get_write_time(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status status() const {
- return __get_status();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status status(error_code& __ec) const noexcept {
- return __get_status(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status symlink_status() const {
- return __get_symlink_status();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status symlink_status(error_code& __ec) const noexcept {
- return __get_symlink_status(&__ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator< (directory_entry const& __rhs) const noexcept {
- return __p_ < __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator==(directory_entry const& __rhs) const noexcept {
- return __p_ == __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator!=(directory_entry const& __rhs) const noexcept {
- return __p_ != __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator<=(directory_entry const& __rhs) const noexcept {
- return __p_ <= __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator> (directory_entry const& __rhs) const noexcept {
- return __p_ > __rhs.__p_;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- bool operator>=(directory_entry const& __rhs) const noexcept {
- return __p_ >= __rhs.__p_;
- }
-
-private:
- friend class directory_iterator;
- friend class recursive_directory_iterator;
- friend class __dir_stream;
-
- enum _CacheType : unsigned char {
- _Empty,
- _IterSymlink,
- _IterNonSymlink,
- _RefreshSymlink,
- _RefreshSymlinkUnresolved,
- _RefreshNonSymlink
- };
-
- struct __cached_data {
- uintmax_t __size_;
- uintmax_t __nlink_;
- file_time_type __write_time_;
- perms __sym_perms_;
- perms __non_sym_perms_;
- file_type __type_;
- _CacheType __cache_type_;
-
- _LIBCPP_INLINE_VISIBILITY
- __cached_data() noexcept { __reset(); }
-
- _LIBCPP_INLINE_VISIBILITY
- void __reset() {
- __cache_type_ = _Empty;
- __type_ = file_type::none;
- __sym_perms_ = __non_sym_perms_ = perms::unknown;
- __size_ = __nlink_ = uintmax_t(-1);
- __write_time_ = file_time_type::min();
- }
- };
-
- _LIBCPP_INLINE_VISIBILITY
- static __cached_data __create_iter_result(file_type __ft) {
- __cached_data __data;
- __data.__type_ = __ft;
- __data.__cache_type_ = [&]() {
- switch (__ft) {
- case file_type::none:
- return _Empty;
- case file_type::symlink:
- return _IterSymlink;
- default:
- return _IterNonSymlink;
- }
- }();
- return __data;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
- __p_ = std::move(__p);
- __data_ = __dt;
- }
-
- _LIBCPP_FUNC_VIS
- error_code __do_refresh() noexcept;
-
- _LIBCPP_INLINE_VISIBILITY
- static bool __is_dne_error(error_code const& __ec) {
- if (!__ec)
- return true;
- switch (static_cast<errc>(__ec.value())) {
- case errc::no_such_file_or_directory:
- case errc::not_a_directory:
- return true;
- default:
- return false;
- }
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void __handle_error(const char* __msg, error_code* __dest_ec,
- error_code const& __ec,
- bool __allow_dne = false) const {
- if (__dest_ec) {
- *__dest_ec = __ec;
- return;
- }
- if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
- __throw_filesystem_error(__msg, __p_, __ec);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- void __refresh(error_code* __ec = nullptr) {
- __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
- /*allow_dne*/ true);
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_type __get_sym_ft(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- return __symlink_status(__p_, __ec).type();
- case _IterSymlink:
- case _RefreshSymlink:
- case _RefreshSymlinkUnresolved:
- if (__ec)
- __ec->clear();
- return file_type::symlink;
- case _IterNonSymlink:
- case _RefreshNonSymlink:
- file_status __st(__data_.__type_);
- if (__ec && !_VSTD_FS::exists(__st))
- *__ec = make_error_code(errc::no_such_file_or_directory);
- else if (__ec)
- __ec->clear();
- return __data_.__type_;
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_type __get_ft(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return __status(__p_, __ec).type();
- case _IterNonSymlink:
- case _RefreshNonSymlink:
- case _RefreshSymlink: {
- file_status __st(__data_.__type_);
- if (__ec && !_VSTD_FS::exists(__st))
- *__ec = make_error_code(errc::no_such_file_or_directory);
- else if (__ec)
- __ec->clear();
- return __data_.__type_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status __get_status(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return __status(__p_, __ec);
- case _RefreshNonSymlink:
- case _RefreshSymlink:
- return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_status __get_symlink_status(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- return __symlink_status(__p_, __ec);
- case _RefreshNonSymlink:
- return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
- case _RefreshSymlink:
- case _RefreshSymlinkUnresolved:
- return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
- }
- _LIBCPP_UNREACHABLE();
- }
-
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t __get_size(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return _VSTD_FS::__file_size(__p_, __ec);
- case _RefreshSymlink:
- case _RefreshNonSymlink: {
- error_code __m_ec;
- file_status __st(__get_ft(&__m_ec));
- __handle_error("in directory_entry::file_size", __ec, __m_ec);
- if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
- errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
- : errc::not_supported;
- __handle_error("in directory_entry::file_size", __ec,
- make_error_code(__err_kind));
- }
- return __data_.__size_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- uintmax_t __get_nlink(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return _VSTD_FS::__hard_link_count(__p_, __ec);
- case _RefreshSymlink:
- case _RefreshNonSymlink: {
- error_code __m_ec;
- (void)__get_ft(&__m_ec);
- __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
- return __data_.__nlink_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-
- _LIBCPP_INLINE_VISIBILITY
- file_time_type __get_write_time(error_code *__ec = nullptr) const {
- switch (__data_.__cache_type_) {
- case _Empty:
- case _IterNonSymlink:
- case _IterSymlink:
- case _RefreshSymlinkUnresolved:
- return _VSTD_FS::__last_write_time(__p_, __ec);
- case _RefreshSymlink:
- case _RefreshNonSymlink: {
- error_code __m_ec;
- file_status __st(__get_ft(&__m_ec));
- __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
- if (_VSTD_FS::exists(__st) &&
- __data_.__write_time_ == file_time_type::min())
- __handle_error("in directory_entry::last_write_time", __ec,
- make_error_code(errc::value_too_large));
- return __data_.__write_time_;
- }
- }
- _LIBCPP_UNREACHABLE();
- }
-private:
- _Path __p_;
- __cached_data __data_;
-};
-
-class __dir_element_proxy {
-public:
-
- inline _LIBCPP_INLINE_VISIBILITY
- directory_entry operator*() { return _VSTD::move(__elem_); }
-
-private:
- friend class directory_iterator;
- friend class recursive_directory_iterator;
- explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
- __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(_VSTD::move(__o.__elem_)) {}
- directory_entry __elem_;
-};
-
-class directory_iterator
-{
-public:
- typedef directory_entry value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type const* pointer;
- typedef value_type const& reference;
- typedef input_iterator_tag iterator_category;
-
-public:
- //ctor & dtor
- directory_iterator() noexcept
- { }
-
- explicit directory_iterator(const path& __p)
- : directory_iterator(__p, nullptr)
- { }
-
- directory_iterator(const path& __p, directory_options __opts)
- : directory_iterator(__p, nullptr, __opts)
- { }
-
- directory_iterator(const path& __p, error_code& __ec)
- : directory_iterator(__p, &__ec)
- { }
-
- directory_iterator(const path& __p, directory_options __opts,
- error_code& __ec)
- : directory_iterator(__p, &__ec, __opts)
- { }
-
- directory_iterator(const directory_iterator&) = default;
- directory_iterator(directory_iterator&&) = default;
- directory_iterator& operator=(const directory_iterator&) = default;
-
- directory_iterator& operator=(directory_iterator&& __o) noexcept {
- // non-default implementation provided to support self-move assign.
- if (this != &__o) {
- __imp_ = _VSTD::move(__o.__imp_);
- }
- return *this;
- }
-
- ~directory_iterator() = default;
-
- const directory_entry& operator*() const {
- _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
- return __dereference();
- }
-
- const directory_entry* operator->() const
- { return &**this; }
-
- directory_iterator& operator++()
- { return __increment(); }
-
- __dir_element_proxy operator++(int) {
- __dir_element_proxy __p(**this);
- __increment();
- return __p;
- }
-
- directory_iterator& increment(error_code& __ec)
- { return __increment(&__ec); }
-
-private:
- inline _LIBCPP_INLINE_VISIBILITY
- friend bool operator==(const directory_iterator& __lhs,
- const directory_iterator& __rhs) noexcept;
-
- // construct the dir_stream
- _LIBCPP_FUNC_VIS
- directory_iterator(const path&, error_code *,
- directory_options = directory_options::none);
-
- _LIBCPP_FUNC_VIS
- directory_iterator& __increment(error_code * __ec = nullptr);
-
- _LIBCPP_FUNC_VIS
- const directory_entry& __dereference() const;
-
-private:
- shared_ptr<__dir_stream> __imp_;
-};
-
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator==(const directory_iterator& __lhs,
- const directory_iterator& __rhs) noexcept {
- return __lhs.__imp_ == __rhs.__imp_;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator!=(const directory_iterator& __lhs,
- const directory_iterator& __rhs) noexcept {
- return !(__lhs == __rhs);
-}
-
-// enable directory_iterator range-based for statements
-inline _LIBCPP_INLINE_VISIBILITY
-directory_iterator begin(directory_iterator __iter) noexcept {
- return __iter;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-directory_iterator end(const directory_iterator&) noexcept {
- return directory_iterator();
-}
-
-class recursive_directory_iterator {
-public:
- using value_type = directory_entry;
- using difference_type = std::ptrdiff_t;
- using pointer = directory_entry const *;
- using reference = directory_entry const &;
- using iterator_category = std::input_iterator_tag;
-
-public:
- // constructors and destructor
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator() noexcept
- : __rec_(false)
- {}
-
- _LIBCPP_INLINE_VISIBILITY
- explicit recursive_directory_iterator(const path& __p,
- directory_options __xoptions = directory_options::none)
- : recursive_directory_iterator(__p, __xoptions, nullptr)
- { }
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator(const path& __p,
- directory_options __xoptions, error_code& __ec)
- : recursive_directory_iterator(__p, __xoptions, &__ec)
- { }
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator(const path& __p, error_code& __ec)
- : recursive_directory_iterator(__p, directory_options::none, &__ec)
- { }
-
- recursive_directory_iterator(const recursive_directory_iterator&) = default;
- recursive_directory_iterator(recursive_directory_iterator&&) = default;
-
- recursive_directory_iterator &
- operator=(const recursive_directory_iterator&) = default;
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator &
- operator=(recursive_directory_iterator&& __o) noexcept {
- // non-default implementation provided to support self-move assign.
- if (this != &__o) {
- __imp_ = _VSTD::move(__o.__imp_);
- __rec_ = __o.__rec_;
- }
- return *this;
- }
-
- ~recursive_directory_iterator() = default;
-
- _LIBCPP_INLINE_VISIBILITY
- const directory_entry& operator*() const
- { return __dereference(); }
-
- _LIBCPP_INLINE_VISIBILITY
- const directory_entry* operator->() const
- { return &__dereference(); }
-
- recursive_directory_iterator& operator++()
- { return __increment(); }
-
- _LIBCPP_INLINE_VISIBILITY
- __dir_element_proxy operator++(int) {
- __dir_element_proxy __p(**this);
- __increment();
- return __p;
- }
-
- _LIBCPP_INLINE_VISIBILITY
- recursive_directory_iterator& increment(error_code& __ec)
- { return __increment(&__ec); }
-
- _LIBCPP_FUNC_VIS directory_options options() const;
- _LIBCPP_FUNC_VIS int depth() const;
-
- _LIBCPP_INLINE_VISIBILITY
- void pop() { __pop(); }
-
- _LIBCPP_INLINE_VISIBILITY
- void pop(error_code& __ec)
- { __pop(&__ec); }
-
- _LIBCPP_INLINE_VISIBILITY
- bool recursion_pending() const
- { return __rec_; }
-
- _LIBCPP_INLINE_VISIBILITY
- void disable_recursion_pending()
- { __rec_ = false; }
-
-private:
- recursive_directory_iterator(const path& __p, directory_options __opt,
- error_code *__ec);
-
- _LIBCPP_FUNC_VIS
- const directory_entry& __dereference() const;
-
- _LIBCPP_FUNC_VIS
- bool __try_recursion(error_code* __ec);
-
- _LIBCPP_FUNC_VIS
- void __advance(error_code* __ec=nullptr);
-
- _LIBCPP_FUNC_VIS
- recursive_directory_iterator& __increment(error_code *__ec=nullptr);
-
- _LIBCPP_FUNC_VIS
- void __pop(error_code* __ec=nullptr);
-
- inline _LIBCPP_INLINE_VISIBILITY
- friend bool operator==(const recursive_directory_iterator&,
- const recursive_directory_iterator&) noexcept;
-
- struct __shared_imp;
- shared_ptr<__shared_imp> __imp_;
- bool __rec_;
-}; // class recursive_directory_iterator
-
-
-inline _LIBCPP_INLINE_VISIBILITY
-bool operator==(const recursive_directory_iterator& __lhs,
- const recursive_directory_iterator& __rhs) noexcept
-{
- return __lhs.__imp_ == __rhs.__imp_;
-}
-
-_LIBCPP_INLINE_VISIBILITY
-inline bool operator!=(const recursive_directory_iterator& __lhs,
- const recursive_directory_iterator& __rhs) noexcept
-{
- return !(__lhs == __rhs);
-}
-// enable recursive_directory_iterator range-based for statements
-inline _LIBCPP_INLINE_VISIBILITY
-recursive_directory_iterator begin(recursive_directory_iterator __iter) noexcept {
- return __iter;
-}
-
-inline _LIBCPP_INLINE_VISIBILITY
-recursive_directory_iterator end(const recursive_directory_iterator&) noexcept {
- return recursive_directory_iterator();
-}
+using namespace _VSTD_FS;
_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
--- /dev/null
+// -*- C++ -*-
+//===--------------------------- filesystem -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef _LIBCPP_FILESYSTEM
+#define _LIBCPP_FILESYSTEM
+/*
+ filesystem synopsis
+
+ namespace std { namespace filesystem {
+
+ class path;
+
+ void swap(path& lhs, path& rhs) noexcept;
+ size_t hash_value(const path& p) noexcept;
+
+ bool operator==(const path& lhs, const path& rhs) noexcept;
+ bool operator!=(const path& lhs, const path& rhs) noexcept;
+ bool operator< (const path& lhs, const path& rhs) noexcept;
+ bool operator<=(const path& lhs, const path& rhs) noexcept;
+ bool operator> (const path& lhs, const path& rhs) noexcept;
+ bool operator>=(const path& lhs, const path& rhs) noexcept;
+
+ path operator/ (const path& lhs, const path& rhs);
+
+ // fs.path.io operators are friends of path.
+ template <class charT, class traits>
+ friend basic_ostream<charT, traits>&
+ operator<<(basic_ostream<charT, traits>& os, const path& p);
+
+ template <class charT, class traits>
+ friend basic_istream<charT, traits>&
+ operator>>(basic_istream<charT, traits>& is, path& p);
+
+ template <class Source>
+ path u8path(const Source& source);
+ template <class InputIterator>
+ path u8path(InputIterator first, InputIterator last);
+
+ class filesystem_error;
+ class directory_entry;
+
+ class directory_iterator;
+
+ // enable directory_iterator range-based for statements
+ directory_iterator begin(directory_iterator iter) noexcept;
+ directory_iterator end(const directory_iterator&) noexcept;
+
+ class recursive_directory_iterator;
+
+ // enable recursive_directory_iterator range-based for statements
+ recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
+ recursive_directory_iterator end(const recursive_directory_iterator&) noexcept;
+
+ class file_status;
+
+ struct space_info
+ {
+ uintmax_t capacity;
+ uintmax_t free;
+ uintmax_t available;
+ };
+
+ enum class file_type;
+ enum class perms;
+ enum class perm_options;
+ enum class copy_options;
+ enum class directory_options;
+
+ typedef chrono::time_point<trivial-clock> file_time_type;
+
+ // operational functions
+
+ path absolute(const path& p);
+ path absolute(const path& p, error_code &ec);
+
+ path canonical(const path& p);
+ path canonical(const path& p, error_code& ec);
+
+ void copy(const path& from, const path& to);
+ void copy(const path& from, const path& to, error_code& ec);
+ void copy(const path& from, const path& to, copy_options options);
+ void copy(const path& from, const path& to, copy_options options,
+ error_code& ec);
+
+ bool copy_file(const path& from, const path& to);
+ bool copy_file(const path& from, const path& to, error_code& ec);
+ bool copy_file(const path& from, const path& to, copy_options option);
+ bool copy_file(const path& from, const path& to, copy_options option,
+ error_code& ec);
+
+ void copy_symlink(const path& existing_symlink, const path& new_symlink);
+ void copy_symlink(const path& existing_symlink, const path& new_symlink,
+ error_code& ec) noexcept;
+
+ bool create_directories(const path& p);
+ bool create_directories(const path& p, error_code& ec);
+
+ bool create_directory(const path& p);
+ bool create_directory(const path& p, error_code& ec) noexcept;
+
+ bool create_directory(const path& p, const path& attributes);
+ bool create_directory(const path& p, const path& attributes,
+ error_code& ec) noexcept;
+
+ void create_directory_symlink(const path& to, const path& new_symlink);
+ void create_directory_symlink(const path& to, const path& new_symlink,
+ error_code& ec) noexcept;
+
+ void create_hard_link(const path& to, const path& new_hard_link);
+ void create_hard_link(const path& to, const path& new_hard_link,
+ error_code& ec) noexcept;
+
+ void create_symlink(const path& to, const path& new_symlink);
+ void create_symlink(const path& to, const path& new_symlink,
+ error_code& ec) noexcept;
+
+ path current_path();
+ path current_path(error_code& ec);
+ void current_path(const path& p);
+ void current_path(const path& p, error_code& ec) noexcept;
+
+ bool exists(file_status s) noexcept;
+ bool exists(const path& p);
+ bool exists(const path& p, error_code& ec) noexcept;
+
+ bool equivalent(const path& p1, const path& p2);
+ bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept;
+
+ uintmax_t file_size(const path& p);
+ uintmax_t file_size(const path& p, error_code& ec) noexcept;
+
+ uintmax_t hard_link_count(const path& p);
+ uintmax_t hard_link_count(const path& p, error_code& ec) noexcept;
+
+ bool is_block_file(file_status s) noexcept;
+ bool is_block_file(const path& p);
+ bool is_block_file(const path& p, error_code& ec) noexcept;
+
+ bool is_character_file(file_status s) noexcept;
+ bool is_character_file(const path& p);
+ bool is_character_file(const path& p, error_code& ec) noexcept;
+
+ bool is_directory(file_status s) noexcept;
+ bool is_directory(const path& p);
+ bool is_directory(const path& p, error_code& ec) noexcept;
+
+ bool is_empty(const path& p);
+ bool is_empty(const path& p, error_code& ec) noexcept;
+
+ bool is_fifo(file_status s) noexcept;
+ bool is_fifo(const path& p);
+ bool is_fifo(const path& p, error_code& ec) noexcept;
+
+ bool is_other(file_status s) noexcept;
+ bool is_other(const path& p);
+ bool is_other(const path& p, error_code& ec) noexcept;
+
+ bool is_regular_file(file_status s) noexcept;
+ bool is_regular_file(const path& p);
+ bool is_regular_file(const path& p, error_code& ec) noexcept;
+
+ bool is_socket(file_status s) noexcept;
+ bool is_socket(const path& p);
+ bool is_socket(const path& p, error_code& ec) noexcept;
+
+ bool is_symlink(file_status s) noexcept;
+ bool is_symlink(const path& p);
+ bool is_symlink(const path& p, error_code& ec) noexcept;
+
+ file_time_type last_write_time(const path& p);
+ file_time_type last_write_time(const path& p, error_code& ec) noexcept;
+ void last_write_time(const path& p, file_time_type new_time);
+ void last_write_time(const path& p, file_time_type new_time,
+ error_code& ec) noexcept;
+
+ void permissions(const path& p, perms prms,
+ perm_options opts=perm_options::replace);
+ void permissions(const path& p, perms prms, error_code& ec) noexcept;
+ 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;
+
+ uintmax_t remove_all(const path& p);
+ uintmax_t remove_all(const path& p, error_code& ec);
+
+ void rename(const path& from, const path& to);
+ void rename(const path& from, const path& to, error_code& ec) noexcept;
+
+ void resize_file(const path& p, uintmax_t size);
+ void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept;
+
+ space_info space(const path& p);
+ space_info space(const path& p, error_code& ec) noexcept;
+
+ file_status status(const path& p);
+ file_status status(const path& p, error_code& ec) noexcept;
+
+ bool status_known(file_status s) noexcept;
+
+ file_status symlink_status(const path& p);
+ file_status symlink_status(const path& p, error_code& ec) noexcept;
+
+ 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::filesystem
+
+*/
+
+#include <__config>
+#include <cstddef>
+#include <cstdlib>
+#include <chrono>
+#include <iterator>
+#include <iosfwd>
+#include <locale>
+#include <memory>
+#include <stack>
+#include <string>
+#include <system_error>
+#include <utility>
+#include <iomanip> // for quoted
+#include <string_view>
+
+#include <__debug>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#ifndef _LIBCPP_CXX03_LANG
+
+#if _LIBCPP_STD_VER >= 17
+#define __cpp_lib_filesystem 201703
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
+
+struct _FilesystemClock {
+#if !defined(_LIBCPP_HAS_NO_INT128)
+ typedef __int128_t rep;
+ typedef nano period;
+#else
+ typedef long long rep;
+ typedef nano period;
+#endif
+
+ typedef chrono::duration<rep, period> duration;
+ typedef chrono::time_point<_FilesystemClock> time_point;
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 const bool is_steady = false;
+
+ _LIBCPP_FUNC_VIS static time_point now() noexcept;
+
+ _LIBCPP_INLINE_VISIBILITY
+ static time_t to_time_t(const time_point& __t) noexcept {
+ typedef chrono::duration<rep> __secs;
+ return time_t(
+ chrono::duration_cast<__secs>(__t.time_since_epoch()).count());
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ static time_point from_time_t(time_t __t) noexcept {
+ typedef chrono::duration<rep> __secs;
+ return time_point(__secs(__t));
+ }
+};
+
+typedef chrono::time_point<_FilesystemClock> file_time_type;
+
+struct _LIBCPP_TYPE_VIS space_info {
+ uintmax_t capacity;
+ uintmax_t free;
+ uintmax_t available;
+};
+
+enum class _LIBCPP_ENUM_VIS file_type : signed char {
+ none = 0,
+ not_found = -1,
+ regular = 1,
+ directory = 2,
+ symlink = 3,
+ block = 4,
+ character = 5,
+ fifo = 6,
+ socket = 7,
+ unknown = 8
+};
+
+enum class _LIBCPP_ENUM_VIS perms : unsigned {
+ none = 0,
+
+ owner_read = 0400,
+ owner_write = 0200,
+ owner_exec = 0100,
+ owner_all = 0700,
+
+ group_read = 040,
+ group_write = 020,
+ group_exec = 010,
+ group_all = 070,
+
+ others_read = 04,
+ others_write = 02,
+ others_exec = 01,
+ others_all = 07,
+
+ all = 0777,
+
+ set_uid = 04000,
+ set_gid = 02000,
+ sticky_bit = 01000,
+ mask = 07777,
+ unknown = 0xFFFF,
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator&(perms _LHS, perms _RHS) {
+ return static_cast<perms>(static_cast<unsigned>(_LHS) &
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator|(perms _LHS, perms _RHS) {
+ return static_cast<perms>(static_cast<unsigned>(_LHS) |
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator^(perms _LHS, perms _RHS) {
+ return static_cast<perms>(static_cast<unsigned>(_LHS) ^
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perms operator~(perms _LHS) {
+ return static_cast<perms>(~static_cast<unsigned>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; }
+
+_LIBCPP_INLINE_VISIBILITY
+inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; }
+
+_LIBCPP_INLINE_VISIBILITY
+inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; }
+
+enum class _LIBCPP_ENUM_VIS perm_options : unsigned char {
+ replace = 1,
+ add = 2,
+ remove = 4,
+ nofollow = 8
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) {
+ return static_cast<perm_options>(static_cast<unsigned>(_LHS) &
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) {
+ return static_cast<perm_options>(static_cast<unsigned>(_LHS) |
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) {
+ return static_cast<perm_options>(static_cast<unsigned>(_LHS) ^
+ static_cast<unsigned>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr perm_options operator~(perm_options _LHS) {
+ return static_cast<perm_options>(~static_cast<unsigned>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) {
+ return _LHS = _LHS & _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) {
+ return _LHS = _LHS | _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) {
+ return _LHS = _LHS ^ _RHS;
+}
+
+enum class _LIBCPP_ENUM_VIS copy_options : unsigned short {
+ none = 0,
+ skip_existing = 1,
+ overwrite_existing = 2,
+ update_existing = 4,
+ recursive = 8,
+ copy_symlinks = 16,
+ skip_symlinks = 32,
+ directories_only = 64,
+ create_symlinks = 128,
+ create_hard_links = 256,
+ __in_recursive_copy = 512,
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) {
+ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) &
+ static_cast<unsigned short>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) {
+ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) |
+ static_cast<unsigned short>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) {
+ return static_cast<copy_options>(static_cast<unsigned short>(_LHS) ^
+ static_cast<unsigned short>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr copy_options operator~(copy_options _LHS) {
+ return static_cast<copy_options>(~static_cast<unsigned short>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) {
+ return _LHS = _LHS & _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) {
+ return _LHS = _LHS | _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) {
+ return _LHS = _LHS ^ _RHS;
+}
+
+enum class _LIBCPP_ENUM_VIS directory_options : unsigned char {
+ none = 0,
+ follow_directory_symlink = 1,
+ skip_permission_denied = 2
+};
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator&(directory_options _LHS,
+ directory_options _RHS) {
+ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) &
+ static_cast<unsigned char>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator|(directory_options _LHS,
+ directory_options _RHS) {
+ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) |
+ static_cast<unsigned char>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator^(directory_options _LHS,
+ directory_options _RHS) {
+ return static_cast<directory_options>(static_cast<unsigned char>(_LHS) ^
+ static_cast<unsigned char>(_RHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline constexpr directory_options operator~(directory_options _LHS) {
+ return static_cast<directory_options>(~static_cast<unsigned char>(_LHS));
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline directory_options& operator&=(directory_options& _LHS,
+ directory_options _RHS) {
+ return _LHS = _LHS & _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline directory_options& operator|=(directory_options& _LHS,
+ directory_options _RHS) {
+ return _LHS = _LHS | _RHS;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline directory_options& operator^=(directory_options& _LHS,
+ directory_options _RHS) {
+ return _LHS = _LHS ^ _RHS;
+}
+
+class _LIBCPP_TYPE_VIS file_status {
+public:
+ // constructors
+ _LIBCPP_INLINE_VISIBILITY
+ file_status() noexcept : file_status(file_type::none) {}
+ _LIBCPP_INLINE_VISIBILITY
+ explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept
+ : __ft_(__ft),
+ __prms_(__prms) {}
+
+ file_status(const file_status&) noexcept = default;
+ file_status(file_status&&) noexcept = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ ~file_status() {}
+
+ file_status& operator=(const file_status&) noexcept = default;
+ file_status& operator=(file_status&&) noexcept = default;
+
+ // observers
+ _LIBCPP_INLINE_VISIBILITY
+ file_type type() const noexcept { return __ft_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ perms permissions() const noexcept { return __prms_; }
+
+ // modifiers
+ _LIBCPP_INLINE_VISIBILITY
+ void type(file_type __ft) noexcept { __ft_ = __ft; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void permissions(perms __p) noexcept { __prms_ = __p; }
+
+private:
+ file_type __ft_;
+ perms __prms_;
+};
+
+class _LIBCPP_TYPE_VIS directory_entry;
+
+template <class _Tp>
+struct __can_convert_char {
+ static const bool value = false;
+};
+template <class _Tp>
+struct __can_convert_char<const _Tp> : public __can_convert_char<_Tp> {};
+template <>
+struct __can_convert_char<char> {
+ static const bool value = true;
+ using __char_type = char;
+};
+template <>
+struct __can_convert_char<wchar_t> {
+ static const bool value = true;
+ using __char_type = wchar_t;
+};
+template <>
+struct __can_convert_char<char16_t> {
+ static const bool value = true;
+ using __char_type = char16_t;
+};
+template <>
+struct __can_convert_char<char32_t> {
+ static const bool value = true;
+ using __char_type = char32_t;
+};
+
+template <class _ECharT>
+typename enable_if<__can_convert_char<_ECharT>::value, bool>::type
+__is_separator(_ECharT __e) {
+ return __e == _ECharT('/');
+};
+
+struct _NullSentinal {};
+
+template <class _Tp>
+using _Void = void;
+
+template <class _Tp, class = void>
+struct __is_pathable_string : public false_type {};
+
+template <class _ECharT, class _Traits, class _Alloc>
+struct __is_pathable_string<
+ basic_string<_ECharT, _Traits, _Alloc>,
+ _Void<typename __can_convert_char<_ECharT>::__char_type> >
+ : public __can_convert_char<_ECharT> {
+ using _Str = basic_string<_ECharT, _Traits, _Alloc>;
+ using _Base = __can_convert_char<_ECharT>;
+ static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
+ static _ECharT const* __range_end(_Str const& __s) {
+ return __s.data() + __s.length();
+ }
+ static _ECharT __first_or_null(_Str const& __s) {
+ return __s.empty() ? _ECharT{} : __s[0];
+ }
+};
+
+template <class _ECharT, class _Traits>
+struct __is_pathable_string<
+ basic_string_view<_ECharT, _Traits>,
+ _Void<typename __can_convert_char<_ECharT>::__char_type> >
+ : public __can_convert_char<_ECharT> {
+ using _Str = basic_string_view<_ECharT, _Traits>;
+ using _Base = __can_convert_char<_ECharT>;
+ static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); }
+ static _ECharT const* __range_end(_Str const& __s) {
+ return __s.data() + __s.length();
+ }
+ static _ECharT __first_or_null(_Str const& __s) {
+ return __s.empty() ? _ECharT{} : __s[0];
+ }
+};
+
+template <class _Source, class _DS = typename decay<_Source>::type,
+ class _UnqualPtrType =
+ typename remove_const<typename remove_pointer<_DS>::type>::type,
+ bool _IsCharPtr = is_pointer<_DS>::value&&
+ __can_convert_char<_UnqualPtrType>::value>
+struct __is_pathable_char_array : false_type {};
+
+template <class _Source, class _ECharT, class _UPtr>
+struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true>
+ : __can_convert_char<typename remove_const<_ECharT>::type> {
+ using _Base = __can_convert_char<typename remove_const<_ECharT>::type>;
+
+ static _ECharT const* __range_begin(const _ECharT* __b) { return __b; }
+ static _ECharT const* __range_end(const _ECharT* __b) {
+ using _Iter = const _ECharT*;
+ const _ECharT __sentinal = _ECharT{};
+ _Iter __e = __b;
+ for (; *__e != __sentinal; ++__e)
+ ;
+ return __e;
+ }
+
+ static _ECharT __first_or_null(const _ECharT* __b) { return *__b; }
+};
+
+template <class _Iter, bool _IsIt = __is_input_iterator<_Iter>::value,
+ class = void>
+struct __is_pathable_iter : false_type {};
+
+template <class _Iter>
+struct __is_pathable_iter<
+ _Iter, true,
+ _Void<typename __can_convert_char<
+ typename iterator_traits<_Iter>::value_type>::__char_type> >
+ : __can_convert_char<typename iterator_traits<_Iter>::value_type> {
+ using _ECharT = typename iterator_traits<_Iter>::value_type;
+ using _Base = __can_convert_char<_ECharT>;
+
+ static _Iter __range_begin(_Iter __b) { return __b; }
+ static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; }
+
+ static _ECharT __first_or_null(_Iter __b) { return *__b; }
+};
+
+template <class _Tp, bool _IsStringT = __is_pathable_string<_Tp>::value,
+ bool _IsCharIterT = __is_pathable_char_array<_Tp>::value,
+ bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value>
+struct __is_pathable : false_type {
+ static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false");
+};
+
+template <class _Tp>
+struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {};
+
+template <class _Tp>
+struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {
+};
+
+template <class _Tp>
+struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {};
+
+template <class _ECharT>
+struct _PathCVT {
+ static_assert(__can_convert_char<_ECharT>::value,
+ "Char type not convertible");
+
+ typedef __narrow_to_utf8<sizeof(_ECharT) * __CHAR_BIT__> _Narrower;
+
+ static void __append_range(string& __dest, _ECharT const* __b,
+ _ECharT const* __e) {
+ _Narrower()(back_inserter(__dest), __b, __e);
+ }
+
+ template <class _Iter>
+ static void __append_range(string& __dest, _Iter __b, _Iter __e) {
+ static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
+ if (__b == __e)
+ return;
+ basic_string<_ECharT> __tmp(__b, __e);
+ _Narrower()(back_inserter(__dest), __tmp.data(),
+ __tmp.data() + __tmp.length());
+ }
+
+ template <class _Iter>
+ static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
+ static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload");
+ const _ECharT __sentinal = _ECharT{};
+ if (*__b == __sentinal)
+ return;
+ basic_string<_ECharT> __tmp;
+ for (; *__b != __sentinal; ++__b)
+ __tmp.push_back(*__b);
+ _Narrower()(back_inserter(__dest), __tmp.data(),
+ __tmp.data() + __tmp.length());
+ }
+
+ template <class _Source>
+ static void __append_source(string& __dest, _Source const& __s) {
+ using _Traits = __is_pathable<_Source>;
+ __append_range(__dest, _Traits::__range_begin(__s),
+ _Traits::__range_end(__s));
+ }
+};
+
+template <>
+struct _PathCVT<char> {
+
+ template <class _Iter>
+ static typename enable_if<__is_exactly_input_iterator<_Iter>::value>::type
+ __append_range(string& __dest, _Iter __b, _Iter __e) {
+ for (; __b != __e; ++__b)
+ __dest.push_back(*__b);
+ }
+
+ template <class _Iter>
+ static typename enable_if<__is_forward_iterator<_Iter>::value>::type
+ __append_range(string& __dest, _Iter __b, _Iter __e) {
+ __dest.__append_forward_unsafe(__b, __e);
+ }
+
+ template <class _Iter>
+ static void __append_range(string& __dest, _Iter __b, _NullSentinal) {
+ const char __sentinal = char{};
+ for (; *__b != __sentinal; ++__b)
+ __dest.push_back(*__b);
+ }
+
+ template <class _Source>
+ static void __append_source(string& __dest, _Source const& __s) {
+ using _Traits = __is_pathable<_Source>;
+ __append_range(__dest, _Traits::__range_begin(__s),
+ _Traits::__range_end(__s));
+ }
+};
+
+class _LIBCPP_TYPE_VIS path {
+ template <class _SourceOrIter, class _Tp = path&>
+ using _EnableIfPathable =
+ typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type;
+
+ template <class _Tp>
+ using _SourceChar = typename __is_pathable<_Tp>::__char_type;
+
+ template <class _Tp>
+ using _SourceCVT = _PathCVT<_SourceChar<_Tp> >;
+
+public:
+ typedef char value_type;
+ typedef basic_string<value_type> string_type;
+ typedef _VSTD::string_view __string_view;
+ static constexpr value_type preferred_separator = '/';
+
+ enum class _LIBCPP_ENUM_VIS format : unsigned char {
+ auto_format,
+ native_format,
+ generic_format
+ };
+
+ // constructors and destructor
+ _LIBCPP_INLINE_VISIBILITY path() noexcept {}
+ _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {}
+ _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept
+ : __pn_(_VSTD::move(__p.__pn_)) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ path(string_type&& __s, format = format::auto_format) noexcept
+ : __pn_(_VSTD::move(__s)) {}
+
+ template <class _Source, class = _EnableIfPathable<_Source, void> >
+ path(const _Source& __src, format = format::auto_format) {
+ _SourceCVT<_Source>::__append_source(__pn_, __src);
+ }
+
+ template <class _InputIt>
+ path(_InputIt __first, _InputIt __last, format = format::auto_format) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
+ }
+
+ // TODO Implement locale conversions.
+ template <class _Source, class = _EnableIfPathable<_Source, void> >
+ path(const _Source& __src, const locale& __loc, format = format::auto_format);
+ template <class _InputIt>
+ path(_InputIt __first, _InputIt _last, const locale& __loc,
+ format = format::auto_format);
+
+ _LIBCPP_INLINE_VISIBILITY
+ ~path() = default;
+
+ // assignments
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator=(const path& __p) {
+ __pn_ = __p.__pn_;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator=(path&& __p) noexcept {
+ __pn_ = _VSTD::move(__p.__pn_);
+ return *this;
+ }
+
+ template <class = void>
+ _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept {
+ __pn_ = _VSTD::move(__s);
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& assign(string_type&& __s) noexcept {
+ __pn_ = _VSTD::move(__s);
+ return *this;
+ }
+
+ template <class _Source>
+ _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source>
+ operator=(const _Source& __src) {
+ return this->assign(__src);
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> assign(const _Source& __src) {
+ __pn_.clear();
+ _SourceCVT<_Source>::__append_source(__pn_, __src);
+ return *this;
+ }
+
+ template <class _InputIt>
+ path& assign(_InputIt __first, _InputIt __last) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ __pn_.clear();
+ _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
+ return *this;
+ }
+
+private:
+ template <class _ECharT>
+ static bool __source_is_absolute(_ECharT __first_or_null) {
+ return __is_separator(__first_or_null);
+ }
+
+public:
+ // appends
+ path& operator/=(const path& __p) {
+ 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>
+ operator/=(const _Source& __src) {
+ return this->append(__src);
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> append(const _Source& __src) {
+ using _Traits = __is_pathable<_Source>;
+ using _CVT = _PathCVT<_SourceChar<_Source> >;
+ 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;
+ }
+
+ template <class _InputIt>
+ path& append(_InputIt __first, _InputIt __last) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ static_assert(__can_convert_char<_ItVal>::value, "Must convertible");
+ using _CVT = _PathCVT<_ItVal>;
+ if (__first != __last && __source_is_absolute(*__first))
+ __pn_.clear();
+ else if (has_filename())
+ __pn_ += preferred_separator;
+ _CVT::__append_range(__pn_, __first, __last);
+ return *this;
+ }
+
+ // concatenation
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(const path& __x) {
+ __pn_ += __x.__pn_;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(const string_type& __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(__string_view __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(const value_type* __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& operator+=(value_type __x) {
+ __pn_ += __x;
+ return *this;
+ }
+
+ template <class _ECharT>
+ typename enable_if<__can_convert_char<_ECharT>::value, path&>::type
+ operator+=(_ECharT __x) {
+ basic_string<_ECharT> __tmp;
+ __tmp += __x;
+ _PathCVT<_ECharT>::__append_source(__pn_, __tmp);
+ return *this;
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> operator+=(const _Source& __x) {
+ return this->concat(__x);
+ }
+
+ template <class _Source>
+ _EnableIfPathable<_Source> concat(const _Source& __x) {
+ _SourceCVT<_Source>::__append_source(__pn_, __x);
+ return *this;
+ }
+
+ template <class _InputIt>
+ path& concat(_InputIt __first, _InputIt __last) {
+ typedef typename iterator_traits<_InputIt>::value_type _ItVal;
+ _PathCVT<_ItVal>::__append_range(__pn_, __first, __last);
+ return *this;
+ }
+
+ // modifiers
+ _LIBCPP_INLINE_VISIBILITY
+ void clear() noexcept { __pn_.clear(); }
+
+ path& make_preferred() { return *this; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ path& remove_filename() {
+ auto __fname = __filename();
+ if (!__fname.empty())
+ __pn_.erase(__fname.data() - __pn_.data());
+ return *this;
+ }
+
+ path& replace_filename(const path& __replacement) {
+ remove_filename();
+ return (*this /= __replacement);
+ }
+
+ path& replace_extension(const path& __replacement = path());
+
+ _LIBCPP_INLINE_VISIBILITY
+ void swap(path& __rhs) noexcept { __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 { return __pn_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const value_type* c_str() const noexcept { return __pn_.c_str(); }
+
+ _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
+
+ template <class _ECharT, class _Traits = char_traits<_ECharT>,
+ class _Allocator = allocator<_ECharT> >
+ basic_string<_ECharT, _Traits, _Allocator>
+ string(const _Allocator& __a = _Allocator()) const {
+ using _CVT = __widen_from_utf8<sizeof(_ECharT) * __CHAR_BIT__>;
+ using _Str = basic_string<_ECharT, _Traits, _Allocator>;
+ _Str __s(__a);
+ __s.reserve(__pn_.size());
+ _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size());
+ return __s;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; }
+ _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const {
+ return string<wchar_t>();
+ }
+ _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; }
+ _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const {
+ return string<char16_t>();
+ }
+ _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const {
+ return string<char32_t>();
+ }
+
+ // generic format observers
+ template <class _ECharT, class _Traits = char_traits<_ECharT>,
+ class _Allocator = allocator<_ECharT> >
+ basic_string<_ECharT, _Traits, _Allocator>
+ generic_string(const _Allocator& __a = _Allocator()) const {
+ return string<_ECharT, _Traits, _Allocator>(__a);
+ }
+
+ std::string generic_string() const { return __pn_; }
+ std::wstring generic_wstring() const { return string<wchar_t>(); }
+ std::string generic_u8string() const { return __pn_; }
+ std::u16string generic_u16string() const { return string<char16_t>(); }
+ std::u32string generic_u32string() const { return string<char32_t>(); }
+
+private:
+ int __compare(__string_view) const;
+ __string_view __root_name() const;
+ __string_view __root_directory() const;
+ __string_view __root_path_raw() const;
+ __string_view __relative_path() const;
+ __string_view __parent_path() const;
+ __string_view __filename() const;
+ __string_view __stem() const;
+ __string_view __extension() const;
+
+public:
+ // compare
+ _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept {
+ return __compare(__p.__pn_);
+ }
+ _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const {
+ return __compare(__s);
+ }
+ _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const {
+ return __compare(__s);
+ }
+ _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const {
+ return __compare(__s);
+ }
+
+ // decomposition
+ _LIBCPP_INLINE_VISIBILITY path root_name() const {
+ return string_type(__root_name());
+ }
+ _LIBCPP_INLINE_VISIBILITY path root_directory() const {
+ return string_type(__root_directory());
+ }
+ _LIBCPP_INLINE_VISIBILITY path root_path() const {
+ return root_name().append(string_type(__root_directory()));
+ }
+ _LIBCPP_INLINE_VISIBILITY path relative_path() const {
+ return string_type(__relative_path());
+ }
+ _LIBCPP_INLINE_VISIBILITY path parent_path() const {
+ return string_type(__parent_path());
+ }
+ _LIBCPP_INLINE_VISIBILITY path filename() const {
+ return string_type(__filename());
+ }
+ _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); }
+ _LIBCPP_INLINE_VISIBILITY path extension() const {
+ return string_type(__extension());
+ }
+
+ // query
+ _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool
+ empty() const noexcept {
+ return __pn_.empty();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY bool has_root_name() const {
+ return !__root_name().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const {
+ return !__root_directory().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_root_path() const {
+ return !__root_path_raw().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const {
+ return !__relative_path().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const {
+ return !__parent_path().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_filename() const {
+ return !__filename().empty();
+ }
+ _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); }
+ _LIBCPP_INLINE_VISIBILITY bool has_extension() const {
+ return !__extension().empty();
+ }
+
+ _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;
+
+ iterator begin() const;
+ iterator end() const;
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_INLINE_VISIBILITY friend
+ typename enable_if<is_same<_CharT, char>::value &&
+ is_same<_Traits, char_traits<char> >::value,
+ basic_ostream<_CharT, _Traits>&>::type
+ operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
+ __os << std::__quoted(__p.native());
+ return __os;
+ }
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_INLINE_VISIBILITY friend
+ typename enable_if<!is_same<_CharT, char>::value ||
+ !is_same<_Traits, char_traits<char> >::value,
+ basic_ostream<_CharT, _Traits>&>::type
+ operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) {
+ __os << std::__quoted(__p.string<_CharT, _Traits>());
+ return __os;
+ }
+
+ template <class _CharT, class _Traits>
+ _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>&
+ operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) {
+ basic_string<_CharT, _Traits> __tmp;
+ __is >> __quoted(__tmp);
+ __p = __tmp;
+ return __is;
+ }
+
+private:
+ inline _LIBCPP_INLINE_VISIBILITY path&
+ __assign_view(__string_view const& __s) noexcept {
+ __pn_ = string_type(__s);
+ return *this;
+ }
+ string_type __pn_;
+};
+
+inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept {
+ __lhs.swap(__rhs);
+}
+
+_LIBCPP_FUNC_VIS
+size_t hash_value(const path& __p) noexcept;
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs,
+ const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) == 0;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs,
+ const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) != 0;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs,
+ const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) < 0;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs,
+ const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) <= 0;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs,
+ const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) > 0;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs,
+ const path& __rhs) noexcept {
+ return __lhs.compare(__rhs) >= 0;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs,
+ const path& __rhs) {
+ path __result(__lhs);
+ __result /= __rhs;
+ return __result;
+}
+
+template <class _Source>
+_LIBCPP_INLINE_VISIBILITY
+ typename enable_if<__is_pathable<_Source>::value, path>::type
+ u8path(const _Source& __s) {
+ static_assert(
+ is_same<typename __is_pathable<_Source>::__char_type, char>::value,
+ "u8path(Source const&) requires Source have a character type of type "
+ "'char'");
+ return path(__s);
+}
+
+template <class _InputIt>
+_LIBCPP_INLINE_VISIBILITY
+ typename enable_if<__is_pathable<_InputIt>::value, path>::type
+ u8path(_InputIt __f, _InputIt __l) {
+ static_assert(
+ is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
+ "u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
+ return path(__f, __l);
+}
+
+class _LIBCPP_TYPE_VIS path::iterator {
+public:
+ enum _ParserState : unsigned char {
+ _Singular,
+ _BeforeBegin,
+ _InRootName,
+ _InRootDir,
+ _InFilenames,
+ _InTrailingSep,
+ _AtEnd
+ };
+
+public:
+ typedef bidirectional_iterator_tag iterator_category;
+
+ typedef path value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef const path* pointer;
+ typedef const path& reference;
+
+ typedef void
+ __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator
+
+public:
+ _LIBCPP_INLINE_VISIBILITY
+ iterator()
+ : __stashed_elem_(), __path_ptr_(nullptr), __entry_(),
+ __state_(_Singular) {}
+
+ iterator(const iterator&) = default;
+ ~iterator() = default;
+
+ iterator& operator=(const iterator&) = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ reference operator*() const { return __stashed_elem_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ pointer operator->() const { return &__stashed_elem_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator& operator++() {
+ _LIBCPP_ASSERT(__state_ != _Singular,
+ "attempting to increment a singular iterator");
+ _LIBCPP_ASSERT(__state_ != _AtEnd,
+ "attempting to increment the end iterator");
+ return __increment();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator operator++(int) {
+ iterator __it(*this);
+ this->operator++();
+ return __it;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator& operator--() {
+ _LIBCPP_ASSERT(__state_ != _Singular,
+ "attempting to decrement a singular iterator");
+ _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(),
+ "attempting to decrement the begin iterator");
+ return __decrement();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ iterator operator--(int) {
+ iterator __it(*this);
+ this->operator--();
+ return __it;
+ }
+
+private:
+ friend class path;
+
+ inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&,
+ const iterator&);
+
+ iterator& __increment();
+ iterator& __decrement();
+
+ path __stashed_elem_;
+ const path* __path_ptr_;
+ path::__string_view __entry_;
+ _ParserState __state_;
+};
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs,
+ const path::iterator& __rhs) {
+ return __lhs.__path_ptr_ == __rhs.__path_ptr_ &&
+ __lhs.__entry_.data() == __rhs.__entry_.data();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs,
+ const path::iterator& __rhs) {
+ return !(__lhs == __rhs);
+}
+
+class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error {
+public:
+ _LIBCPP_INLINE_VISIBILITY
+ filesystem_error(const string& __what, error_code __ec)
+ : system_error(__ec, __what),
+ __storage_(make_shared<_Storage>(path(), path())) {
+ __create_what(0);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ filesystem_error(const string& __what, const path& __p1, error_code __ec)
+ : system_error(__ec, __what),
+ __storage_(make_shared<_Storage>(__p1, path())) {
+ __create_what(1);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ filesystem_error(const string& __what, const path& __p1, const path& __p2,
+ error_code __ec)
+ : system_error(__ec, __what),
+ __storage_(make_shared<_Storage>(__p1, __p2)) {
+ __create_what(2);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const path& path1() const noexcept { return __storage_->__p1_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const path& path2() const noexcept { return __storage_->__p2_; }
+
+ ~filesystem_error() override; // key function
+
+ _LIBCPP_INLINE_VISIBILITY
+ const char* what() const noexcept override {
+ return __storage_->__what_.c_str();
+ }
+
+ _LIBCPP_FUNC_VIS
+ void __create_what(int __num_paths);
+
+private:
+ struct _Storage {
+ _LIBCPP_INLINE_VISIBILITY
+ _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
+
+ path __p1_;
+ path __p2_;
+ string __what_;
+ };
+ shared_ptr<_Storage> __storage_;
+};
+
+template <class... _Args>
+_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY
+#ifndef _LIBCPP_NO_EXCEPTIONS
+ void
+ __throw_filesystem_error(_Args&&... __args) {
+ throw filesystem_error(std::forward<_Args>(__args)...);
+}
+#else
+ void
+ __throw_filesystem_error(_Args&&...) {
+ _VSTD::abort();
+}
+#endif
+
+// operational functions
+
+_LIBCPP_FUNC_VIS
+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);
+_LIBCPP_FUNC_VIS
+bool __copy_file(const path& __from, const path& __to, copy_options __opt,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __copy_symlink(const path& __existing_symlink, const path& __new_symlink,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __create_directories(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __create_directory(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __create_directory(const path& p, const path& attributes,
+ error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __create_directory_symlink(const path& __to, const path& __new_symlink,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __create_hard_link(const path& __to, const path& __new_hard_link,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __create_symlink(const path& __to, const path& __new_symlink,
+ error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+path __current_path(error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __current_path(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __equivalent(const path&, const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+uintmax_t __file_size(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __fs_is_empty(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+file_time_type __last_write_time(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __last_write_time(const path& p, file_time_type new_time,
+ error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __permissions(const path&, perms, perm_options, error_code* = nullptr);
+_LIBCPP_FUNC_VIS
+path __read_symlink(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+bool __remove(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+uintmax_t __remove_all(const path& p, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __rename(const path& from, const path& to, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr);
+_LIBCPP_FUNC_VIS
+space_info __space(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+file_status __status(const path&, error_code* __ec = nullptr);
+_LIBCPP_FUNC_VIS
+file_status __symlink_status(const path&, error_code* __ec = nullptr);
+_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() {
+ return __current_path();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) {
+ return __current_path(&__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) {
+ __current_path(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p,
+ error_code& __ec) noexcept {
+ __current_path(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) {
+ return __absolute(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p,
+ error_code& __ec) {
+ return __absolute(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) {
+ return __canonical(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p,
+ error_code& __ec) {
+ return __canonical(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from,
+ const path& __to) {
+ __copy(__from, __to, copy_options::none);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
+ error_code& __ec) {
+ __copy(__from, __to, copy_options::none, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
+ copy_options __opt) {
+ __copy(__from, __to, __opt);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to,
+ copy_options __opt,
+ error_code& __ec) {
+ __copy(__from, __to, __opt, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
+ const path& __to) {
+ return __copy_file(__from, __to, copy_options::none);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+copy_file(const path& __from, const path& __to, error_code& __ec) {
+ return __copy_file(__from, __to, copy_options::none, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+copy_file(const path& __from, const path& __to, copy_options __opt) {
+ return __copy_file(__from, __to, __opt);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from,
+ const path& __to,
+ copy_options __opt,
+ error_code& __ec) {
+ return __copy_file(__from, __to, __opt, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing,
+ const path& __new) {
+ __copy_symlink(__existing, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept {
+ __copy_symlink(__ext, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) {
+ return __create_directories(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p,
+ error_code& __ec) {
+ return __create_directories(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) {
+ return __create_directory(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+create_directory(const path& __p, error_code& __ec) noexcept {
+ return __create_directory(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p,
+ const path& __attrs) {
+ return __create_directory(__p, __attrs);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+create_directory(const path& __p, const path& __attrs,
+ error_code& __ec) noexcept {
+ return __create_directory(__p, __attrs, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_directory_symlink(const path& __to, const path& __new) {
+ __create_directory_symlink(__to, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_directory_symlink(const path& __to, const path& __new,
+ error_code& __ec) noexcept {
+ __create_directory_symlink(__to, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to,
+ const path& __new) {
+ __create_hard_link(__to, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_hard_link(const path& __to, const path& __new,
+ error_code& __ec) noexcept {
+ __create_hard_link(__to, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to,
+ const path& __new) {
+ __create_symlink(__to, __new);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept {
+ return __create_symlink(__to, __new, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept {
+ return __s.type() != file_type::none;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept {
+ return status_known(__s) && __s.type() != file_type::not_found;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) {
+ return exists(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p,
+ error_code& __ec) noexcept {
+ auto __s = __status(__p, &__ec);
+ if (status_known(__s))
+ __ec.clear();
+ return exists(__s);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1,
+ const path& __p2) {
+ return __equivalent(__p1, __p2);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept {
+ return __equivalent(__p1, __p2, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) {
+ return __file_size(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t
+file_size(const path& __p, error_code& __ec) noexcept {
+ return __file_size(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) {
+ return __hard_link_count(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t
+hard_link_count(const path& __p, error_code& __ec) noexcept {
+ return __hard_link_count(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept {
+ return __s.type() == file_type::block;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) {
+ return is_block_file(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p,
+ error_code& __ec) noexcept {
+ return is_block_file(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_character_file(file_status __s) noexcept {
+ return __s.type() == file_type::character;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) {
+ return is_character_file(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_character_file(const path& __p, error_code& __ec) noexcept {
+ return is_character_file(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept {
+ return __s.type() == file_type::directory;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) {
+ return is_directory(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p,
+ error_code& __ec) noexcept {
+ return is_directory(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) {
+ return __fs_is_empty(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p,
+ error_code& __ec) {
+ return __fs_is_empty(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept {
+ return __s.type() == file_type::fifo;
+}
+inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) {
+ return is_fifo(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p,
+ error_code& __ec) noexcept {
+ return is_fifo(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_regular_file(file_status __s) noexcept {
+ return __s.type() == file_type::regular;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) {
+ return is_regular_file(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+is_regular_file(const path& __p, error_code& __ec) noexcept {
+ return is_regular_file(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept {
+ return __s.type() == file_type::socket;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) {
+ return is_socket(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p,
+ error_code& __ec) noexcept {
+ return is_socket(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept {
+ return __s.type() == file_type::symlink;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) {
+ return is_symlink(__symlink_status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p,
+ error_code& __ec) noexcept {
+ return is_symlink(__symlink_status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept {
+ return exists(__s) && !is_regular_file(__s) && !is_directory(__s) &&
+ !is_symlink(__s);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) {
+ return is_other(__status(__p));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p,
+ error_code& __ec) noexcept {
+ return is_other(__status(__p, &__ec));
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_time_type
+last_write_time(const path& __p) {
+ return __last_write_time(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_time_type
+last_write_time(const path& __p, error_code& __ec) noexcept {
+ return __last_write_time(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p,
+ file_time_type __t) {
+ __last_write_time(__p, __t);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+last_write_time(const path& __p, file_time_type __t,
+ error_code& __ec) noexcept {
+ __last_write_time(__p, __t, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+permissions(const path& __p, perms __prms,
+ perm_options __opts = perm_options::replace) {
+ __permissions(__p, __prms, __opts);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
+ error_code& __ec) noexcept {
+ __permissions(__p, __prms, perm_options::replace, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms,
+ perm_options __opts,
+ error_code& __ec) {
+ __permissions(__p, __prms, __opts, &__ec);
+}
+
+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);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY 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);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p,
+ error_code& __ec) noexcept {
+ return __remove(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) {
+ return __remove_all(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p,
+ error_code& __ec) {
+ return __remove_all(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from,
+ const path& __to) {
+ return __rename(__from, __to);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+rename(const path& __from, const path& __to, error_code& __ec) noexcept {
+ return __rename(__from, __to, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p,
+ uintmax_t __ns) {
+ return __resize_file(__p, __ns);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY void
+resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
+ return __resize_file(__p, __ns, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) {
+ return __space(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p,
+ error_code& __ec) noexcept {
+ return __space(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) {
+ return __status(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p,
+ error_code& __ec) noexcept {
+ return __status(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) {
+ return __symlink_status(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY file_status
+symlink_status(const path& __p, error_code& __ec) noexcept {
+ return __symlink_status(__p, &__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() {
+ return __temp_directory_path();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) {
+ return __temp_directory_path(&__ec);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) {
+ return __weakly_canonical(__p);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p,
+ error_code& __ec) {
+ return __weakly_canonical(__p, &__ec);
+}
+
+class directory_iterator;
+class recursive_directory_iterator;
+class __dir_stream;
+
+class directory_entry {
+ typedef _VSTD_FS::path _Path;
+
+public:
+ // constructors and destructors
+ directory_entry() noexcept = default;
+ directory_entry(directory_entry const&) = default;
+ directory_entry(directory_entry&&) noexcept = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ explicit directory_entry(_Path const& __p) : __p_(__p) {
+ error_code __ec;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) {
+ __refresh(&__ec);
+ }
+
+ ~directory_entry() {}
+
+ directory_entry& operator=(directory_entry const&) = default;
+ directory_entry& operator=(directory_entry&&) noexcept = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ void assign(_Path const& __p) {
+ __p_ = __p;
+ error_code __ec;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void assign(_Path const& __p, error_code& __ec) {
+ __p_ = __p;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void replace_filename(_Path const& __p) {
+ __p_.replace_filename(__p);
+ error_code __ec;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void replace_filename(_Path const& __p, error_code& __ec) {
+ __p_ = __p_.parent_path() / __p;
+ __refresh(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void refresh() { __refresh(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void refresh(error_code& __ec) noexcept { __refresh(&__ec); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ _Path const& path() const noexcept { return __p_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ operator const _Path&() const noexcept { return __p_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool exists(error_code& __ec) const noexcept {
+ return _VSTD_FS::exists(file_status{__get_ft(&__ec)});
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_block_file() const { return __get_ft() == file_type::block; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_block_file(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::block;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_character_file() const { return __get_ft() == file_type::character; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_character_file(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::character;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_directory() const { return __get_ft() == file_type::directory; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_directory(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::directory;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_fifo() const { return __get_ft() == file_type::fifo; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_fifo(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::fifo;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_other(error_code& __ec) const noexcept {
+ return _VSTD_FS::is_other(file_status{__get_ft(&__ec)});
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_regular_file() const { return __get_ft() == file_type::regular; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_regular_file(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::regular;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_socket() const { return __get_ft() == file_type::socket; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_socket(error_code& __ec) const noexcept {
+ return __get_ft(&__ec) == file_type::socket;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_symlink() const { return __get_sym_ft() == file_type::symlink; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool is_symlink(error_code& __ec) const noexcept {
+ return __get_sym_ft(&__ec) == file_type::symlink;
+ }
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t file_size() const { return __get_size(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t file_size(error_code& __ec) const noexcept {
+ return __get_size(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t hard_link_count() const { return __get_nlink(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t hard_link_count(error_code& __ec) const noexcept {
+ return __get_nlink(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_time_type last_write_time() const { return __get_write_time(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_time_type last_write_time(error_code& __ec) const noexcept {
+ return __get_write_time(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status status() const { return __get_status(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status status(error_code& __ec) const noexcept {
+ return __get_status(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status symlink_status() const { return __get_symlink_status(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status symlink_status(error_code& __ec) const noexcept {
+ return __get_symlink_status(&__ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator<(directory_entry const& __rhs) const noexcept {
+ return __p_ < __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator==(directory_entry const& __rhs) const noexcept {
+ return __p_ == __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator!=(directory_entry const& __rhs) const noexcept {
+ return __p_ != __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator<=(directory_entry const& __rhs) const noexcept {
+ return __p_ <= __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator>(directory_entry const& __rhs) const noexcept {
+ return __p_ > __rhs.__p_;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool operator>=(directory_entry const& __rhs) const noexcept {
+ return __p_ >= __rhs.__p_;
+ }
+
+private:
+ friend class directory_iterator;
+ friend class recursive_directory_iterator;
+ friend class __dir_stream;
+
+ enum _CacheType : unsigned char {
+ _Empty,
+ _IterSymlink,
+ _IterNonSymlink,
+ _RefreshSymlink,
+ _RefreshSymlinkUnresolved,
+ _RefreshNonSymlink
+ };
+
+ struct __cached_data {
+ uintmax_t __size_;
+ uintmax_t __nlink_;
+ file_time_type __write_time_;
+ perms __sym_perms_;
+ perms __non_sym_perms_;
+ file_type __type_;
+ _CacheType __cache_type_;
+
+ _LIBCPP_INLINE_VISIBILITY
+ __cached_data() noexcept { __reset(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __reset() {
+ __cache_type_ = _Empty;
+ __type_ = file_type::none;
+ __sym_perms_ = __non_sym_perms_ = perms::unknown;
+ __size_ = __nlink_ = uintmax_t(-1);
+ __write_time_ = file_time_type::min();
+ }
+ };
+
+ _LIBCPP_INLINE_VISIBILITY
+ static __cached_data __create_iter_result(file_type __ft) {
+ __cached_data __data;
+ __data.__type_ = __ft;
+ __data.__cache_type_ = [&]() {
+ switch (__ft) {
+ case file_type::none:
+ return _Empty;
+ case file_type::symlink:
+ return _IterSymlink;
+ default:
+ return _IterNonSymlink;
+ }
+ }();
+ return __data;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __assign_iter_entry(_Path&& __p, __cached_data __dt) {
+ __p_ = std::move(__p);
+ __data_ = __dt;
+ }
+
+ _LIBCPP_FUNC_VIS
+ error_code __do_refresh() noexcept;
+
+ _LIBCPP_INLINE_VISIBILITY
+ static bool __is_dne_error(error_code const& __ec) {
+ if (!__ec)
+ return true;
+ switch (static_cast<errc>(__ec.value())) {
+ case errc::no_such_file_or_directory:
+ case errc::not_a_directory:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __handle_error(const char* __msg, error_code* __dest_ec,
+ error_code const& __ec, bool __allow_dne = false) const {
+ if (__dest_ec) {
+ *__dest_ec = __ec;
+ return;
+ }
+ if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
+ __throw_filesystem_error(__msg, __p_, __ec);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void __refresh(error_code* __ec = nullptr) {
+ __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
+ /*allow_dne*/ true);
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_type __get_sym_ft(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ return __symlink_status(__p_, __ec).type();
+ case _IterSymlink:
+ case _RefreshSymlink:
+ case _RefreshSymlinkUnresolved:
+ if (__ec)
+ __ec->clear();
+ return file_type::symlink;
+ case _IterNonSymlink:
+ case _RefreshNonSymlink:
+ file_status __st(__data_.__type_);
+ if (__ec && !_VSTD_FS::exists(__st))
+ *__ec = make_error_code(errc::no_such_file_or_directory);
+ else if (__ec)
+ __ec->clear();
+ return __data_.__type_;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_type __get_ft(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return __status(__p_, __ec).type();
+ case _IterNonSymlink:
+ case _RefreshNonSymlink:
+ case _RefreshSymlink: {
+ file_status __st(__data_.__type_);
+ if (__ec && !_VSTD_FS::exists(__st))
+ *__ec = make_error_code(errc::no_such_file_or_directory);
+ else if (__ec)
+ __ec->clear();
+ return __data_.__type_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status __get_status(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return __status(__p_, __ec);
+ case _RefreshNonSymlink:
+ case _RefreshSymlink:
+ return file_status(__get_ft(__ec), __data_.__non_sym_perms_);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_status __get_symlink_status(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ return __symlink_status(__p_, __ec);
+ case _RefreshNonSymlink:
+ return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_);
+ case _RefreshSymlink:
+ case _RefreshSymlinkUnresolved:
+ return file_status(__get_sym_ft(__ec), __data_.__sym_perms_);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t __get_size(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return _VSTD_FS::__file_size(__p_, __ec);
+ case _RefreshSymlink:
+ case _RefreshNonSymlink: {
+ error_code __m_ec;
+ file_status __st(__get_ft(&__m_ec));
+ __handle_error("in directory_entry::file_size", __ec, __m_ec);
+ if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
+ errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
+ : errc::not_supported;
+ __handle_error("in directory_entry::file_size", __ec,
+ make_error_code(__err_kind));
+ }
+ return __data_.__size_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ uintmax_t __get_nlink(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return _VSTD_FS::__hard_link_count(__p_, __ec);
+ case _RefreshSymlink:
+ case _RefreshNonSymlink: {
+ error_code __m_ec;
+ (void)__get_ft(&__m_ec);
+ __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
+ return __data_.__nlink_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ file_time_type __get_write_time(error_code* __ec = nullptr) const {
+ switch (__data_.__cache_type_) {
+ case _Empty:
+ case _IterNonSymlink:
+ case _IterSymlink:
+ case _RefreshSymlinkUnresolved:
+ return _VSTD_FS::__last_write_time(__p_, __ec);
+ case _RefreshSymlink:
+ case _RefreshNonSymlink: {
+ error_code __m_ec;
+ file_status __st(__get_ft(&__m_ec));
+ __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
+ if (_VSTD_FS::exists(__st) &&
+ __data_.__write_time_ == file_time_type::min())
+ __handle_error("in directory_entry::last_write_time", __ec,
+ make_error_code(errc::value_too_large));
+ return __data_.__write_time_;
+ }
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+private:
+ _Path __p_;
+ __cached_data __data_;
+};
+
+class __dir_element_proxy {
+public:
+ inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() {
+ return _VSTD::move(__elem_);
+ }
+
+private:
+ friend class directory_iterator;
+ friend class recursive_directory_iterator;
+ explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {}
+ __dir_element_proxy(__dir_element_proxy&& __o)
+ : __elem_(_VSTD::move(__o.__elem_)) {}
+ directory_entry __elem_;
+};
+
+class directory_iterator {
+public:
+ typedef directory_entry value_type;
+ typedef ptrdiff_t difference_type;
+ typedef value_type const* pointer;
+ typedef value_type const& reference;
+ typedef input_iterator_tag iterator_category;
+
+public:
+ //ctor & dtor
+ directory_iterator() noexcept {}
+
+ explicit directory_iterator(const path& __p)
+ : directory_iterator(__p, nullptr) {}
+
+ directory_iterator(const path& __p, directory_options __opts)
+ : directory_iterator(__p, nullptr, __opts) {}
+
+ directory_iterator(const path& __p, error_code& __ec)
+ : directory_iterator(__p, &__ec) {}
+
+ directory_iterator(const path& __p, directory_options __opts,
+ error_code& __ec)
+ : directory_iterator(__p, &__ec, __opts) {}
+
+ directory_iterator(const directory_iterator&) = default;
+ directory_iterator(directory_iterator&&) = default;
+ directory_iterator& operator=(const directory_iterator&) = default;
+
+ directory_iterator& operator=(directory_iterator&& __o) noexcept {
+ // non-default implementation provided to support self-move assign.
+ if (this != &__o) {
+ __imp_ = _VSTD::move(__o.__imp_);
+ }
+ return *this;
+ }
+
+ ~directory_iterator() = default;
+
+ const directory_entry& operator*() const {
+ _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced");
+ return __dereference();
+ }
+
+ const directory_entry* operator->() const { return &**this; }
+
+ directory_iterator& operator++() { return __increment(); }
+
+ __dir_element_proxy operator++(int) {
+ __dir_element_proxy __p(**this);
+ __increment();
+ return __p;
+ }
+
+ directory_iterator& increment(error_code& __ec) { return __increment(&__ec); }
+
+private:
+ inline _LIBCPP_INLINE_VISIBILITY friend bool
+ operator==(const directory_iterator& __lhs,
+ const directory_iterator& __rhs) noexcept;
+
+ // construct the dir_stream
+ _LIBCPP_FUNC_VIS
+ directory_iterator(const path&, error_code*,
+ directory_options = directory_options::none);
+
+ _LIBCPP_FUNC_VIS
+ directory_iterator& __increment(error_code* __ec = nullptr);
+
+ _LIBCPP_FUNC_VIS
+ const directory_entry& __dereference() const;
+
+private:
+ shared_ptr<__dir_stream> __imp_;
+};
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+operator==(const directory_iterator& __lhs,
+ const directory_iterator& __rhs) noexcept {
+ return __lhs.__imp_ == __rhs.__imp_;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+operator!=(const directory_iterator& __lhs,
+ const directory_iterator& __rhs) noexcept {
+ return !(__lhs == __rhs);
+}
+
+// enable directory_iterator range-based for statements
+inline _LIBCPP_INLINE_VISIBILITY directory_iterator
+begin(directory_iterator __iter) noexcept {
+ return __iter;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY directory_iterator
+end(const directory_iterator&) noexcept {
+ return directory_iterator();
+}
+
+class recursive_directory_iterator {
+public:
+ using value_type = directory_entry;
+ using difference_type = std::ptrdiff_t;
+ using pointer = directory_entry const*;
+ using reference = directory_entry const&;
+ using iterator_category = std::input_iterator_tag;
+
+public:
+ // constructors and destructor
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator() noexcept : __rec_(false) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ explicit recursive_directory_iterator(
+ const path& __p, directory_options __xoptions = directory_options::none)
+ : recursive_directory_iterator(__p, __xoptions, nullptr) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator(const path& __p, directory_options __xoptions,
+ error_code& __ec)
+ : recursive_directory_iterator(__p, __xoptions, &__ec) {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator(const path& __p, error_code& __ec)
+ : recursive_directory_iterator(__p, directory_options::none, &__ec) {}
+
+ recursive_directory_iterator(const recursive_directory_iterator&) = default;
+ recursive_directory_iterator(recursive_directory_iterator&&) = default;
+
+ recursive_directory_iterator&
+ operator=(const recursive_directory_iterator&) = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator&
+ operator=(recursive_directory_iterator&& __o) noexcept {
+ // non-default implementation provided to support self-move assign.
+ if (this != &__o) {
+ __imp_ = _VSTD::move(__o.__imp_);
+ __rec_ = __o.__rec_;
+ }
+ return *this;
+ }
+
+ ~recursive_directory_iterator() = default;
+
+ _LIBCPP_INLINE_VISIBILITY
+ const directory_entry& operator*() const { return __dereference(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ const directory_entry* operator->() const { return &__dereference(); }
+
+ recursive_directory_iterator& operator++() { return __increment(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ __dir_element_proxy operator++(int) {
+ __dir_element_proxy __p(**this);
+ __increment();
+ return __p;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ recursive_directory_iterator& increment(error_code& __ec) {
+ return __increment(&__ec);
+ }
+
+ _LIBCPP_FUNC_VIS directory_options options() const;
+ _LIBCPP_FUNC_VIS int depth() const;
+
+ _LIBCPP_INLINE_VISIBILITY
+ void pop() { __pop(); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void pop(error_code& __ec) { __pop(&__ec); }
+
+ _LIBCPP_INLINE_VISIBILITY
+ bool recursion_pending() const { return __rec_; }
+
+ _LIBCPP_INLINE_VISIBILITY
+ void disable_recursion_pending() { __rec_ = false; }
+
+private:
+ recursive_directory_iterator(const path& __p, directory_options __opt,
+ error_code* __ec);
+
+ _LIBCPP_FUNC_VIS
+ const directory_entry& __dereference() const;
+
+ _LIBCPP_FUNC_VIS
+ bool __try_recursion(error_code* __ec);
+
+ _LIBCPP_FUNC_VIS
+ void __advance(error_code* __ec = nullptr);
+
+ _LIBCPP_FUNC_VIS
+ recursive_directory_iterator& __increment(error_code* __ec = nullptr);
+
+ _LIBCPP_FUNC_VIS
+ void __pop(error_code* __ec = nullptr);
+
+ inline _LIBCPP_INLINE_VISIBILITY friend bool
+ operator==(const recursive_directory_iterator&,
+ const recursive_directory_iterator&) noexcept;
+
+ struct __shared_imp;
+ shared_ptr<__shared_imp> __imp_;
+ bool __rec_;
+}; // class recursive_directory_iterator
+
+inline _LIBCPP_INLINE_VISIBILITY bool
+operator==(const recursive_directory_iterator& __lhs,
+ const recursive_directory_iterator& __rhs) noexcept {
+ return __lhs.__imp_ == __rhs.__imp_;
+}
+
+_LIBCPP_INLINE_VISIBILITY
+inline bool operator!=(const recursive_directory_iterator& __lhs,
+ const recursive_directory_iterator& __rhs) noexcept {
+ return !(__lhs == __rhs);
+}
+// enable recursive_directory_iterator range-based for statements
+inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
+begin(recursive_directory_iterator __iter) noexcept {
+ return __iter;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator
+end(const recursive_directory_iterator&) noexcept {
+ return recursive_directory_iterator();
+}
+
+_LIBCPP_END_NAMESPACE_FILESYSTEM
+
+#endif // !_LIBCPP_CXX03_LANG
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_FILESYSTEM
bool is_open() const;
basic_filebuf* open(const char* s, ios_base::openmode mode);
basic_filebuf* open(const string& s, ios_base::openmode mode);
+ basic_filebuf* open(const filesystem::path& p, ios_base::openmode mode); // C++17
basic_filebuf* close();
protected:
basic_ifstream();
explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in);
explicit basic_ifstream(const string& s, ios_base::openmode mode = ios_base::in);
+ explicit basic_ifstream(const filesystem::path& p,
+ ios_base::openmode mode = ios_base::in); // C++17
basic_ifstream(basic_ifstream&& rhs);
basic_ifstream& operator=(basic_ifstream&& rhs);
bool is_open() const;
void open(const char* s, ios_base::openmode mode = ios_base::in);
void open(const string& s, ios_base::openmode mode = ios_base::in);
+ void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in); // C++17
+
void close();
};
basic_ofstream();
explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out);
+ explicit basic_ofstream(const filesystem::path& p,
+ ios_base::openmode mode = ios_base::out); // C++17
basic_ofstream(basic_ofstream&& rhs);
basic_ofstream& operator=(basic_ofstream&& rhs);
bool is_open() const;
void open(const char* s, ios_base::openmode mode = ios_base::out);
void open(const string& s, ios_base::openmode mode = ios_base::out);
+ void open(const filesystem::path& p,
+ ios_base::openmode mode = ios_base::out); // C++17
+
void close();
};
basic_fstream();
explicit basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);
explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);
+ explicit basic_fstream(const filesystem::path& p,
+ ios_base::openmode mode = ios_base::in|ios_base::out); C++17
basic_fstream(basic_fstream&& rhs);
basic_fstream& operator=(basic_fstream&& rhs);
bool is_open() const;
void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);
void open(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);
+ void open(const filesystem::path& s,
+ ios_base::openmode mode = ios_base::in|ios_base::out); // C++17
+
void close();
};
#include <__locale>
#include <cstdio>
#include <cstdlib>
+#include <filesystem>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
_LIBCPP_INLINE_VISIBILITY
basic_filebuf* open(const string& __s, ios_base::openmode __mode);
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ basic_filebuf* open(const _VSTD_FS::path& __p, ios_base::openmode __mode) {
+ return open(__p.c_str(), __mode);
+ }
+#endif
_LIBCPP_INLINE_VISIBILITY
basic_filebuf* __open(int __fd, ios_base::openmode __mode);
#endif
#endif
_LIBCPP_INLINE_VISIBILITY
explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ explicit basic_ifstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in)
+ : basic_ifstream(__p.c_str(), __mode) {}
+#endif // _LIBCPP_STD_VER >= 17
#endif
#ifndef _LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
#endif
void open(const string& __s, ios_base::openmode __mode = ios_base::in);
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ void open(const filesystem::path& __p,
+ ios_base::openmode __mode = ios_base::in) {
+ return open(__p.c_str(), __mode);
+ }
+#endif // _LIBCPP_STD_VER >= 17
_LIBCPP_INLINE_VISIBILITY
void __open(int __fd, ios_base::openmode __mode);
#endif
_LIBCPP_INLINE_VISIBILITY
explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out);
+
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ explicit basic_ofstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out)
+ : basic_ofstream(__p.c_str(), __mode) {}
+#endif // _LIBCPP_STD_VER >= 17
+
#ifndef _LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
basic_ofstream(basic_ofstream&& __rhs);
#endif
void open(const string& __s, ios_base::openmode __mode = ios_base::out);
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out)
+ { return open(__p.c_str(), __mode); }
+#endif // _LIBCPP_STD_VER >= 17
+
_LIBCPP_INLINE_VISIBILITY
void __open(int __fd, ios_base::openmode __mode);
#endif
#endif
_LIBCPP_INLINE_VISIBILITY
explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
+
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ explicit basic_fstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in | ios_base::out)
+ : basic_fstream(__p.c_str(), __mode) {}
+#endif // _LIBCPP_STD_VER >= 17
+
#endif
#ifndef _LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
#endif
void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
+
+#if _LIBCPP_STD_VER >= 17
+ _LIBCPP_INLINE_VISIBILITY
+ void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in|ios_base::out)
+ { return open(__p.c_str(), __mode); }
+#endif // _LIBCPP_STD_VER >= 17
+
#endif
_LIBCPP_INLINE_VISIBILITY
void close();
header "exception"
export *
}
+ module filesystem {
+ header "filesystem"
+ export *
+ }
module forward_list {
header "forward_list"
export initializer_list
# Add a meta-target for both libraries.
add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS})
+
+if (LIBCXX_ENABLE_FILESYSTEM)
+ set(LIBCXX_FILESYSTEM_SOURCES
+ ../src/filesystem/operations.cpp
+ ../src/filesystem/directory_iterator.cpp)
+
+ # Filesystem uses __int128_t, which requires a definition of __muloi4 when
+ # compiled with UBSAN. This definition is not provided by libgcc_s, but is
+ # provided by compiler-rt. So we need to disable it to avoid having multiple
+ # definitions. See filesystem/int128_builtins.cpp.
+ if (NOT LIBCXX_USE_COMPILER_RT)
+ list(APPEND LIBCXX_FILESYSTEM_SOURCES ../src/filesystem/int128_builtins.cpp)
+ endif()
+
+ add_library(cxx_filesystem STATIC ${LIBCXX_FILESYSTEM_SOURCES})
+ if (LIBCXX_ENABLE_SHARED)
+ target_link_libraries(cxx_filesystem cxx_shared)
+ else()
+ target_link_libraries(cxx_filesystem cxx_static)
+ endif()
+
+ set(filesystem_flags "${LIBCXX_COMPILE_FLAGS}")
+ check_flag_supported(-std=c++14)
+ if (NOT MSVC AND LIBCXX_SUPPORTS_STD_EQ_CXX14_FLAG)
+ string(REPLACE "-std=c++11" "-std=c++14" filesystem_flags "${LIBCXX_COMPILE_FLAGS}")
+ endif()
+ set_target_properties(cxx_filesystem
+ PROPERTIES
+ COMPILE_FLAGS "${filesystem_flags}"
+ OUTPUT_NAME "c++fs"
+ )
+endif()
+
+
if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
file(GLOB LIBCXX_EXPERIMENTAL_SOURCES ../src/experimental/*.cpp)
- if (LIBCXX_ENABLE_FILESYSTEM)
- file(GLOB LIBCXX_FILESYSTEM_SOURCES ../src/experimental/filesystem/*.cpp)
- endif()
- add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES} ${LIBCXX_FILESYSTEM_SOURCES})
+ add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES})
if (LIBCXX_ENABLE_SHARED)
target_link_libraries(cxx_experimental cxx_shared)
else()
)
endif()
+
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp)
endif()
if (LIBCXX_INSTALL_LIBRARY)
+ if (LIBCXX_INSTALL_FILESYSTEM_LIBRARY)
+ set(filesystem_lib cxx_filesystem)
+ endif()
if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
set(experimental_lib cxx_experimental)
endif()
- install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${experimental_lib}
+ install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${filesystem_lib} ${experimental_lib}
LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx
ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx
)
if(LIBCXX_INSTALL_LIBRARY)
set(lib_install_target cxx)
endif()
+ if (LIBCXX_INSTALL_FILESYSTEM_LIBRARY)
+ set(filesystem_lib_install_target cxx_filesystem)
+ endif()
if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
set(experimental_lib_install_target cxx_experimental)
endif()
add_custom_target(install-cxx
DEPENDS ${lib_install_target}
${experimental_lib_install_target}
+ ${filesystem_lib_install_target}
${header_install_target}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=cxx
add_custom_target(install-cxx-stripped
DEPENDS ${lib_install_target}
${experimental_lib_install_target}
+ ${filesystem_lib_install_target}
${header_install_target}
COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=cxx
+++ /dev/null
-//===------------------ directory_iterator.cpp ----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "experimental/filesystem"
-#include "__config"
-#if defined(_LIBCPP_WIN32API)
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#else
-#include <dirent.h>
-#endif
-#include <errno.h>
-
-#include "filesystem_common.h"
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
-
-namespace detail {
-namespace {
-
-#if !defined(_LIBCPP_WIN32API)
-template <class DirEntT, class = decltype(DirEntT::d_type)>
-static file_type get_file_type(DirEntT *ent, int) {
- switch (ent->d_type) {
- case DT_BLK:
- return file_type::block;
- case DT_CHR:
- return file_type::character;
- case DT_DIR:
- return file_type::directory;
- case DT_FIFO:
- return file_type::fifo;
- case DT_LNK:
- return file_type::symlink;
- case DT_REG:
- return file_type::regular;
- case DT_SOCK:
- return file_type::socket;
- // Unlike in lstat, hitting "unknown" here simply means that the underlying
- // filesystem doesn't support d_type. Report is as 'none' so we correctly
- // set the cache to empty.
- case DT_UNKNOWN:
- break;
- }
- return file_type::none;
-}
-
-template <class DirEntT>
-static file_type get_file_type(DirEntT *ent, long) {
- return file_type::none;
-}
-
-static pair<string_view, file_type>
-posix_readdir(DIR *dir_stream, error_code& ec) {
- struct dirent* dir_entry_ptr = nullptr;
- errno = 0; // zero errno in order to detect errors
- ec.clear();
- if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
- if (errno)
- ec = capture_errno();
- return {};
- } else {
- return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)};
- }
-}
-#else
-
-static file_type get_file_type(const WIN32_FIND_DATA& data) {
- //auto attrs = data.dwFileAttributes;
- // FIXME(EricWF)
- return file_type::unknown;
-}
-static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
- return (data.nFileSizeHight * (MAXDWORD+1)) + data.nFileSizeLow;
-}
-static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
- ULARGE_INTEGER tmp;
- FILETIME& time = data.ftLastWriteTime;
- tmp.u.LowPart = time.dwLowDateTime;
- tmp.u.HighPart = time.dwHighDateTime;
- return file_time_type(file_time_type::duration(time.QuadPart));
-}
-
-#endif
-
-} // namespace
-} // namespace detail
-
-using detail::ErrorHandler;
-
-#if defined(_LIBCPP_WIN32API)
-class __dir_stream {
-public:
-
- __dir_stream() = delete;
- __dir_stream& operator=(const __dir_stream&) = delete;
-
- __dir_stream(__dir_stream&& __ds) noexcept
- : __stream_(__ds.__stream_), __root_(move(__ds.__root_)),
- __entry_(move(__ds.__entry_)) {
- __ds.__stream_ = INVALID_HANDLE_VALUE;
- }
-
- __dir_stream(const path& root, directory_options opts, error_code& ec)
- : __stream_(INVALID_HANDLE_VALUE), __root_(root) {
- __stream_ = ::FindFirstFileEx(root.c_str(), &__data_);
- if (__stream_ == INVALID_HANDLE_VALUE) {
- ec = error_code(::GetLastError(), generic_category());
- const bool ignore_permission_denied =
- bool(opts & directory_options::skip_permission_denied);
- if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
- ec.clear();
- return;
- }
- }
-
- ~__dir_stream() noexcept {
- if (__stream_ == INVALID_HANDLE_VALUE)
- return;
- close();
- }
-
- bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }
-
- bool advance(error_code& ec) {
- while (::FindNextFile(__stream_, &__data_)) {
- if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
- continue;
- // FIXME: Cache more of this
- //directory_entry::__cached_data cdata;
- //cdata.__type_ = get_file_type(__data_);
- //cdata.__size_ = get_file_size(__data_);
- //cdata.__write_time_ = get_write_time(__data_);
- __entry_.__assign_iter_entry(
- __root_ / __data_.cFileName,
- directory_entry::__create_iter_result(get_file_type(__data)));
- return true;
- }
- ec = error_code(::GetLastError(), generic_category());
- close();
- return false;
- }
-
-private:
- error_code close() noexcept {
- error_code ec;
- if (!::FindClose(__stream_))
- ec = error_code(::GetLastError(), generic_category());
- __stream_ = INVALID_HANDLE_VALUE;
- return ec;
- }
-
- HANDLE __stream_{INVALID_HANDLE_VALUE};
- WIN32_FIND_DATA __data_;
-
-public:
- path __root_;
- directory_entry __entry_;
-};
-#else
-class __dir_stream {
-public:
- __dir_stream() = delete;
- __dir_stream& operator=(const __dir_stream&) = delete;
-
- __dir_stream(__dir_stream&& other) noexcept
- : __stream_(other.__stream_), __root_(move(other.__root_)),
- __entry_(move(other.__entry_))
- {
- other.__stream_ = nullptr;
- }
-
-
- __dir_stream(const path& root, directory_options opts, error_code& ec)
- : __stream_(nullptr),
- __root_(root)
- {
- if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
- ec = detail::capture_errno();
- const bool allow_eacess =
- bool(opts & directory_options::skip_permission_denied);
- if (allow_eacess && ec.value() == EACCES)
- ec.clear();
- return;
- }
- advance(ec);
- }
-
- ~__dir_stream() noexcept
- { if (__stream_) close(); }
-
- bool good() const noexcept { return __stream_ != nullptr; }
-
- bool advance(error_code &ec) {
- while (true) {
- auto str_type_pair = detail::posix_readdir(__stream_, ec);
- auto& str = str_type_pair.first;
- if (str == "." || str == "..") {
- continue;
- } else if (ec || str.empty()) {
- close();
- return false;
- } else {
- __entry_.__assign_iter_entry(
- __root_ / str,
- directory_entry::__create_iter_result(str_type_pair.second));
- return true;
- }
- }
- }
-private:
- error_code close() noexcept {
- error_code m_ec;
- if (::closedir(__stream_) == -1)
- m_ec = detail::capture_errno();
- __stream_ = nullptr;
- return m_ec;
- }
-
- DIR * __stream_{nullptr};
-public:
- path __root_;
- directory_entry __entry_;
-};
-#endif
-
-// directory_iterator
-
-directory_iterator::directory_iterator(const path& p, error_code *ec,
- directory_options opts)
-{
- ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p);
-
- error_code m_ec;
- __imp_ = make_shared<__dir_stream>(p, opts, m_ec);
- if (ec)
- *ec = m_ec;
- if (!__imp_->good()) {
- __imp_.reset();
- if (m_ec)
- err.report(m_ec);
- }
-}
-
-directory_iterator& directory_iterator::__increment(error_code *ec)
-{
- _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
- ErrorHandler<void> err("directory_iterator::operator++()", ec);
-
- error_code m_ec;
- if (!__imp_->advance(m_ec)) {
- path root = move(__imp_->__root_);
- __imp_.reset();
- if (m_ec)
- err.report(m_ec, "at root \"%s\"", root);
- }
- return *this;
-
-}
-
-directory_entry const& directory_iterator::__dereference() const {
- _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
- return __imp_->__entry_;
-}
-
-// recursive_directory_iterator
-
-struct recursive_directory_iterator::__shared_imp {
- stack<__dir_stream> __stack_;
- directory_options __options_;
-};
-
-recursive_directory_iterator::recursive_directory_iterator(const path& p,
- directory_options opt, error_code *ec)
- : __imp_(nullptr), __rec_(true)
-{
- ErrorHandler<void> err("recursive_directory_iterator", ec, &p);
-
- error_code m_ec;
- __dir_stream new_s(p, opt, m_ec);
- if (m_ec)
- err.report(m_ec);
- if (m_ec || !new_s.good())
- return;
-
- __imp_ = make_shared<__shared_imp>();
- __imp_->__options_ = opt;
- __imp_->__stack_.push(move(new_s));
-}
-
-void recursive_directory_iterator::__pop(error_code* ec)
-{
- _LIBCPP_ASSERT(__imp_, "Popping the end iterator");
- if (ec) ec->clear();
- __imp_->__stack_.pop();
- if (__imp_->__stack_.size() == 0)
- __imp_.reset();
- else
- __advance(ec);
-}
-
-directory_options recursive_directory_iterator::options() const {
- return __imp_->__options_;
-}
-
-int recursive_directory_iterator::depth() const {
- return __imp_->__stack_.size() - 1;
-}
-
-const directory_entry& recursive_directory_iterator::__dereference() const {
- return __imp_->__stack_.top().__entry_;
-}
-
-recursive_directory_iterator&
-recursive_directory_iterator::__increment(error_code *ec)
-{
- if (ec) ec->clear();
- if (recursion_pending()) {
- if (__try_recursion(ec) || (ec && *ec))
- return *this;
- }
- __rec_ = true;
- __advance(ec);
- return *this;
-}
-
-void recursive_directory_iterator::__advance(error_code* ec) {
- ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
-
- const directory_iterator end_it;
- auto& stack = __imp_->__stack_;
- error_code m_ec;
- while (stack.size() > 0) {
- if (stack.top().advance(m_ec))
- return;
- if (m_ec)
- break;
- stack.pop();
- }
-
- if (m_ec) {
- path root = move(stack.top().__root_);
- __imp_.reset();
- err.report(m_ec, "at root \"%s\"", root);
- } else {
- __imp_.reset();
- }
-}
-
-bool recursive_directory_iterator::__try_recursion(error_code *ec) {
- ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
-
- bool rec_sym = bool(options() & directory_options::follow_directory_symlink);
-
- auto& curr_it = __imp_->__stack_.top();
-
- bool skip_rec = false;
- error_code m_ec;
- if (!rec_sym) {
- file_status st(curr_it.__entry_.__get_sym_ft(&m_ec));
- if (m_ec && status_known(st))
- m_ec.clear();
- if (m_ec || is_symlink(st) || !is_directory(st))
- skip_rec = true;
- } else {
- file_status st(curr_it.__entry_.__get_ft(&m_ec));
- if (m_ec && status_known(st))
- m_ec.clear();
- if (m_ec || !is_directory(st))
- skip_rec = true;
- }
-
- if (!skip_rec) {
- __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
- if (new_it.good()) {
- __imp_->__stack_.push(move(new_it));
- return true;
- }
- }
- if (m_ec) {
- const bool allow_eacess = bool(__imp_->__options_
- & directory_options::skip_permission_denied);
- if (m_ec.value() == EACCES && allow_eacess) {
- if (ec) ec->clear();
- } else {
- path at_ent = move(curr_it.__entry_.__p_);
- __imp_.reset();
- err.report(m_ec, "attempting recursion into \"%s\"", at_ent);
- }
- }
- return false;
-}
-
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
+++ /dev/null
-//===----------------------------------------------------------------------===////
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===////
-
-#ifndef FILESYSTEM_COMMON_H
-#define FILESYSTEM_COMMON_H
-
-#include "experimental/__config"
-#include "array"
-#include "chrono"
-#include "cstdlib"
-#include "climits"
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/time.h> // for ::utimes as used in __last_write_time
-#include <fcntl.h> /* values for fchmodat */
-
-#include <experimental/filesystem>
-
-#include "../../include/apple_availability.h"
-
-#if !defined(__APPLE__)
-// We can use the presence of UTIME_OMIT to detect platforms that provide
-// utimensat.
-#if defined(UTIME_OMIT)
-#define _LIBCPP_USE_UTIMENSAT
-#endif
-#endif
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
-
-namespace detail {
-namespace {
-
-static string format_string_imp(const char* msg, ...) {
- // we might need a second shot at this, so pre-emptivly make a copy
- struct GuardVAList {
- va_list& target;
- bool active = true;
- GuardVAList(va_list &target) : target(target), active(true) {}
- void clear() {
- if (active)
- va_end(target);
- active = false;
- }
- ~GuardVAList() {
- if (active)
- va_end(target);
- }
- };
- va_list args;
- va_start(args, msg);
- GuardVAList args_guard(args);
-
- va_list args_cp;
- va_copy(args_cp, args);
- GuardVAList args_copy_guard(args_cp);
-
- array<char, 256> local_buff;
- size_t size = local_buff.size();
- auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp);
-
- args_copy_guard.clear();
-
- // handle empty expansion
- if (ret == 0)
- return string{};
- if (static_cast<size_t>(ret) < size)
- return string(local_buff.data());
-
- // we did not provide a long enough buffer on our first attempt.
- // add 1 to size to account for null-byte in size cast to prevent overflow
- size = static_cast<size_t>(ret) + 1;
- auto buff_ptr = unique_ptr<char[]>(new char[size]);
- ret = ::vsnprintf(buff_ptr.get(), size, msg, args);
- return string(buff_ptr.get());
-}
-
-const char* unwrap(string const& s) { return s.c_str(); }
-const char* unwrap(path const& p) { return p.native().c_str(); }
-template <class Arg>
-Arg const& unwrap(Arg const& a) {
- static_assert(!is_class<Arg>::value, "cannot pass class here");
- return a;
-}
-
-template <class... Args>
-string format_string(const char* fmt, Args const&... args) {
- return format_string_imp(fmt, unwrap(args)...);
-}
-
-error_code capture_errno() {
- _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
- return error_code(errno, generic_category());
-}
-
-template <class T>
-T error_value();
-template <>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
-template <>
-bool error_value<bool>() {
- return false;
-}
-template <>
-uintmax_t error_value<uintmax_t>() {
- return uintmax_t(-1);
-}
-template <>
-_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
- return file_time_type::min();
-}
-template <>
-path error_value<path>() {
- return {};
-}
-
-template <class T>
-struct ErrorHandler {
- const char* func_name;
- error_code* ec = nullptr;
- const path* p1 = nullptr;
- const path* p2 = nullptr;
-
- ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
- const path* p2 = nullptr)
- : func_name(fname), ec(ec), p1(p1), p2(p2) {
- if (ec)
- ec->clear();
- }
-
- T report(const error_code& m_ec) const {
- if (ec) {
- *ec = m_ec;
- return error_value<T>();
- }
- string what = string("in ") + func_name;
- switch (bool(p1) + bool(p2)) {
- case 0:
- __throw_filesystem_error(what, m_ec);
- case 1:
- __throw_filesystem_error(what, *p1, m_ec);
- case 2:
- __throw_filesystem_error(what, *p1, *p2, m_ec);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- template <class... Args>
- T report(const error_code& m_ec, const char* msg, Args const&... args) const {
- if (ec) {
- *ec = m_ec;
- return error_value<T>();
- }
- string what =
- string("in ") + func_name + ": " + format_string(msg, args...);
- switch (bool(p1) + bool(p2)) {
- case 0:
- __throw_filesystem_error(what, m_ec);
- case 1:
- __throw_filesystem_error(what, *p1, m_ec);
- case 2:
- __throw_filesystem_error(what, *p1, *p2, m_ec);
- }
- _LIBCPP_UNREACHABLE();
- }
-
- T report(errc const& err) const { return report(make_error_code(err)); }
-
- template <class... Args>
- T report(errc const& err, const char* msg, Args const&... args) const {
- return report(make_error_code(err), msg, args...);
- }
-
-private:
- ErrorHandler(ErrorHandler const&) = delete;
- ErrorHandler& operator=(ErrorHandler const&) = delete;
-};
-
-using chrono::duration;
-using chrono::duration_cast;
-
-using TimeSpec = struct ::timespec;
-using StatT = struct ::stat;
-
-template <class FileTimeT, class TimeT,
- bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
-struct time_util_base {
- using rep = typename FileTimeT::rep;
- using fs_duration = typename FileTimeT::duration;
- using fs_seconds = duration<rep>;
- using fs_nanoseconds = duration<rep, nano>;
- using fs_microseconds = duration<rep, micro>;
-
- static constexpr rep max_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
-
- static constexpr rep max_nsec =
- duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
- fs_seconds(max_seconds))
- .count();
-
- static constexpr rep min_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
-
- static constexpr rep min_nsec_timespec =
- duration_cast<fs_nanoseconds>(
- (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
- fs_seconds(1))
- .count();
-
-private:
-#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
- static constexpr fs_duration get_min_nsecs() {
- return duration_cast<fs_duration>(
- fs_nanoseconds(min_nsec_timespec) -
- duration_cast<fs_nanoseconds>(fs_seconds(1)));
- }
- // Static assert that these values properly round trip.
- static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
- FileTimeT::duration::min(),
- "value doesn't roundtrip");
-
- static constexpr bool check_range() {
- // This kinda sucks, but it's what happens when we don't have __int128_t.
- if (sizeof(TimeT) == sizeof(rep)) {
- typedef duration<long long, ratio<3600 * 24 * 365> > Years;
- return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
- duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
- }
- return max_seconds >= numeric_limits<TimeT>::max() &&
- min_seconds <= numeric_limits<TimeT>::min();
- }
- static_assert(check_range(), "the representable range is unacceptable small");
-#endif
-};
-
-template <class FileTimeT, class TimeT>
-struct time_util_base<FileTimeT, TimeT, true> {
- using rep = typename FileTimeT::rep;
- using fs_duration = typename FileTimeT::duration;
- using fs_seconds = duration<rep>;
- using fs_nanoseconds = duration<rep, nano>;
- using fs_microseconds = duration<rep, micro>;
-
- static const rep max_seconds;
- static const rep max_nsec;
- static const rep min_seconds;
- static const rep min_nsec_timespec;
-};
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
- time_util_base<FileTimeT, TimeT, true>::max_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
- duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
- fs_seconds(max_seconds))
- .count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
- time_util_base<FileTimeT, TimeT, true>::min_seconds =
- duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
-
-template <class FileTimeT, class TimeT>
-const typename FileTimeT::rep
- time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
- duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
- fs_seconds(min_seconds)) +
- fs_seconds(1))
- .count();
-
-template <class FileTimeT, class TimeT, class TimeSpecT>
-struct time_util : time_util_base<FileTimeT, TimeT> {
- using Base = time_util_base<FileTimeT, TimeT>;
- using Base::max_nsec;
- using Base::max_seconds;
- using Base::min_nsec_timespec;
- using Base::min_seconds;
-
- using typename Base::fs_duration;
- using typename Base::fs_microseconds;
- using typename Base::fs_nanoseconds;
- using typename Base::fs_seconds;
-
-public:
- template <class CType, class ChronoType>
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
- ChronoType time) {
- using Lim = numeric_limits<CType>;
- if (time > Lim::max() || time < Lim::min())
- return false;
- *out = static_cast<CType>(time);
- return true;
- }
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
- if (tm.tv_sec >= 0) {
- return tm.tv_sec < max_seconds ||
- (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
- } else if (tm.tv_sec == (min_seconds - 1)) {
- return tm.tv_nsec >= min_nsec_timespec;
- } else {
- return tm.tv_sec >= min_seconds;
- }
- }
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
- auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
- auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
- if (nsecs.count() < 0) {
- secs = secs + fs_seconds(1);
- nsecs = nsecs + fs_seconds(1);
- }
- using TLim = numeric_limits<TimeT>;
- if (secs.count() >= 0)
- return secs.count() <= TLim::max();
- return secs.count() >= TLim::min();
- }
-
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
- convert_from_timespec(TimeSpecT tm) {
- if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
- return FileTimeT(fs_seconds(tm.tv_sec) +
- duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
- } else { // tm.tv_sec < 0
- auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
- fs_nanoseconds(tm.tv_nsec));
- auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
- return FileTimeT(Dur);
- }
- }
-
- template <class SubSecT>
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
- set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
- auto dur = tp.time_since_epoch();
- auto sec_dur = duration_cast<fs_seconds>(dur);
- auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
- // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
- if (subsec_dur.count() < 0) {
- if (sec_dur.count() > min_seconds) {
- sec_dur = sec_dur - fs_seconds(1);
- subsec_dur = subsec_dur + fs_seconds(1);
- } else {
- subsec_dur = fs_nanoseconds::zero();
- }
- }
- return checked_set(sec_out, sec_dur.count()) &&
- checked_set(subsec_out, subsec_dur.count());
- }
- static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
- FileTimeT tp) {
- if (!is_representable(tp))
- return false;
- return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
- }
-};
-
-using fs_time = time_util<file_time_type, time_t, TimeSpec>;
-
-#if defined(__APPLE__)
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
-#else
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
-#endif
-
-// allow the utimes implementation to compile even it we're not going
-// to use it.
-
-bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
- error_code& ec) {
- using namespace chrono;
- auto Convert = [](long nsec) {
- using int_type = decltype(std::declval<::timeval>().tv_usec);
- auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
- return static_cast<int_type>(dur);
- };
- struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
- {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
- if (::utimes(p.c_str(), ConvertedTS) == -1) {
- ec = capture_errno();
- return true;
- }
- return false;
-}
-
-#if defined(_LIBCPP_USE_UTIMENSAT)
-bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
- error_code& ec) {
- if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1)
- {
- ec = capture_errno();
- return true;
- }
- return false;
-}
-#endif
-
-bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
- error_code& ec) {
-#if !defined(_LIBCPP_USE_UTIMENSAT)
- return posix_utimes(p, TS, ec);
-#else
- return posix_utimensat(p, TS, ec);
-#endif
-}
-
-
-} // namespace
-} // end namespace detail
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
-
-#endif // FILESYSTEM_COMMON_H
+++ /dev/null
-/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------===
- *
- * The LLVM Compiler Infrastructure
- *
- * This file is dual licensed under the MIT and the University of Illinois Open
- * Source Licenses. See LICENSE.TXT for details.
- *
- * ===----------------------------------------------------------------------===
- *
- * This file implements __muloti4, and is stolen from the compiler_rt library.
- *
- * FIXME: we steal and re-compile it into filesystem, which uses __int128_t,
- * and requires this builtin when sanitized. See llvm.org/PR30643
- *
- * ===----------------------------------------------------------------------===
- */
-#include "__config"
-#include "climits"
-
-#ifndef _LIBCPP_HAS_NO_INT128
-
-extern "C" __attribute__((no_sanitize("undefined")))
-__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) {
- const int N = (int)(sizeof(__int128_t) * CHAR_BIT);
- const __int128_t MIN = (__int128_t)1 << (N - 1);
- const __int128_t MAX = ~MIN;
- *overflow = 0;
- __int128_t result = a * b;
- if (a == MIN) {
- if (b != 0 && b != 1)
- *overflow = 1;
- return result;
- }
- if (b == MIN) {
- if (a != 0 && a != 1)
- *overflow = 1;
- return result;
- }
- __int128_t sa = a >> (N - 1);
- __int128_t abs_a = (a ^ sa) - sa;
- __int128_t sb = b >> (N - 1);
- __int128_t abs_b = (b ^ sb) - sb;
- if (abs_a < 2 || abs_b < 2)
- return result;
- if (sa == sb) {
- if (abs_a > MAX / abs_b)
- *overflow = 1;
- } else {
- if (abs_a > MIN / -abs_b)
- *overflow = 1;
- }
- return result;
-}
-
-#endif
+++ /dev/null
-//===--------------------- filesystem/ops.cpp -----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "experimental/filesystem"
-#include "array"
-#include "iterator"
-#include "fstream"
-#include "random" /* for unique_path */
-#include "string_view"
-#include "type_traits"
-#include "vector"
-#include "cstdlib"
-#include "climits"
-
-#include "filesystem_common.h"
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <time.h>
-#include <fcntl.h> /* values for fchmodat */
-
-#if defined(__linux__)
-# include <linux/version.h>
-# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
-# include <sys/sendfile.h>
-# define _LIBCPP_USE_SENDFILE
-# endif
-#elif defined(__APPLE__) || __has_include(<copyfile.h>)
-#include <copyfile.h>
-# define _LIBCPP_USE_COPYFILE
-#endif
-
-#if !defined(__APPLE__)
-#define _LIBCPP_USE_CLOCK_GETTIME
-#endif
-
-#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
-#include <sys/time.h> // for gettimeofday and timeval
-#endif // !defined(CLOCK_REALTIME)
-
-#if defined(_LIBCPP_COMPILER_GCC)
-#if _GNUC_VER < 500
-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
-#endif
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM
-
-namespace { namespace parser
-{
-
-using string_view_t = path::__string_view;
-using string_view_pair = pair<string_view_t, string_view_t>;
-using PosPtr = path::value_type const*;
-
-struct PathParser {
- enum ParserState : unsigned char {
- // Zero is a special sentinel value used by default constructed iterators.
- PS_BeforeBegin = path::iterator::_BeforeBegin,
- PS_InRootName = path::iterator::_InRootName,
- PS_InRootDir = path::iterator::_InRootDir,
- PS_InFilenames = path::iterator::_InFilenames,
- PS_InTrailingSep = path::iterator::_InTrailingSep,
- PS_AtEnd = path::iterator::_AtEnd
- };
-
- const string_view_t Path;
- string_view_t RawEntry;
- ParserState State;
-
-private:
- PathParser(string_view_t P, ParserState State) noexcept
- : Path(P), State(State) {}
-
-public:
- PathParser(string_view_t P, string_view_t E, unsigned char S)
- : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
- // S cannot be '0' or PS_BeforeBegin.
- }
-
- static PathParser CreateBegin(string_view_t P) noexcept {
- PathParser PP(P, PS_BeforeBegin);
- PP.increment();
- return PP;
- }
-
- static PathParser CreateEnd(string_view_t P) noexcept {
- PathParser PP(P, PS_AtEnd);
- return PP;
- }
-
- PosPtr peek() const noexcept {
- auto TkEnd = getNextTokenStartPos();
- auto End = getAfterBack();
- return TkEnd == End ? nullptr : TkEnd;
- }
-
- void increment() noexcept {
- const PosPtr End = getAfterBack();
- const PosPtr Start = getNextTokenStartPos();
- if (Start == End)
- return makeState(PS_AtEnd);
-
- switch (State) {
- case PS_BeforeBegin: {
- PosPtr TkEnd = consumeSeparator(Start, End);
- if (TkEnd)
- return makeState(PS_InRootDir, Start, TkEnd);
- else
- return makeState(PS_InFilenames, Start, consumeName(Start, End));
- }
- case PS_InRootDir:
- return makeState(PS_InFilenames, Start, consumeName(Start, End));
-
- case PS_InFilenames: {
- PosPtr SepEnd = consumeSeparator(Start, End);
- if (SepEnd != End) {
- PosPtr TkEnd = consumeName(SepEnd, End);
- if (TkEnd)
- return makeState(PS_InFilenames, SepEnd, TkEnd);
- }
- return makeState(PS_InTrailingSep, Start, SepEnd);
- }
-
- case PS_InTrailingSep:
- return makeState(PS_AtEnd);
-
- case PS_InRootName:
- case PS_AtEnd:
- _LIBCPP_UNREACHABLE();
- }
- }
-
- void decrement() noexcept {
- const PosPtr REnd = getBeforeFront();
- const PosPtr RStart = getCurrentTokenStartPos() - 1;
- if (RStart == REnd) // we're decrementing the begin
- return makeState(PS_BeforeBegin);
-
- switch (State) {
- case PS_AtEnd: {
- // Try to consume a trailing separator or root directory first.
- if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
- if (SepEnd == REnd)
- return makeState(PS_InRootDir, Path.data(), RStart + 1);
- return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
- } else {
- PosPtr TkStart = consumeName(RStart, REnd);
- return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
- }
- }
- case PS_InTrailingSep:
- return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, RStart + 1);
- case PS_InFilenames: {
- PosPtr SepEnd = consumeSeparator(RStart, REnd);
- if (SepEnd == REnd)
- return makeState(PS_InRootDir, Path.data(), RStart + 1);
- PosPtr TkEnd = consumeName(SepEnd, REnd);
- return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
- }
- case PS_InRootDir:
- // return makeState(PS_InRootName, Path.data(), RStart + 1);
- case PS_InRootName:
- case PS_BeforeBegin:
- _LIBCPP_UNREACHABLE();
- }
- }
-
- /// \brief Return a view with the "preferred representation" of the current
- /// element. For example trailing separators are represented as a '.'
- string_view_t operator*() const noexcept {
- switch (State) {
- case PS_BeforeBegin:
- case PS_AtEnd:
- return "";
- case PS_InRootDir:
- return "/";
- case PS_InTrailingSep:
- return "";
- case PS_InRootName:
- case PS_InFilenames:
- return RawEntry;
- }
- _LIBCPP_UNREACHABLE();
- }
-
- explicit operator bool() const noexcept {
- return State != PS_BeforeBegin && State != PS_AtEnd;
- }
-
- PathParser& operator++() noexcept {
- increment();
- return *this;
- }
-
- PathParser& operator--() noexcept {
- decrement();
- return *this;
- }
-
- bool inRootPath() const noexcept {
- return State == PS_InRootDir || State == PS_InRootName;
- }
-
-private:
- void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
- State = NewState;
- RawEntry = string_view_t(Start, End - Start);
- }
- void makeState(ParserState NewState) noexcept {
- State = NewState;
- RawEntry = {};
- }
-
- PosPtr getAfterBack() const noexcept {
- return Path.data() + Path.size();
- }
-
- PosPtr getBeforeFront() const noexcept {
- return Path.data() - 1;
- }
-
- /// \brief Return a pointer to the first character after the currently
- /// lexed element.
- PosPtr getNextTokenStartPos() const noexcept {
- switch (State) {
- case PS_BeforeBegin:
- return Path.data();
- case PS_InRootName:
- case PS_InRootDir:
- case PS_InFilenames:
- return &RawEntry.back() + 1;
- case PS_InTrailingSep:
- case PS_AtEnd:
- return getAfterBack();
- }
- _LIBCPP_UNREACHABLE();
- }
-
- /// \brief Return a pointer to the first character in the currently lexed
- /// element.
- PosPtr getCurrentTokenStartPos() const noexcept {
- switch (State) {
- case PS_BeforeBegin:
- case PS_InRootName:
- return &Path.front();
- case PS_InRootDir:
- case PS_InFilenames:
- case PS_InTrailingSep:
- return &RawEntry.front();
- case PS_AtEnd:
- return &Path.back() + 1;
- }
- _LIBCPP_UNREACHABLE();
- }
-
- PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
- if (P == End || *P != '/')
- return nullptr;
- const int Inc = P < End ? 1 : -1;
- P += Inc;
- while (P != End && *P == '/')
- P += Inc;
- return P;
- }
-
- PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
- if (P == End || *P == '/')
- return nullptr;
- const int Inc = P < End ? 1 : -1;
- P += Inc;
- while (P != End && *P != '/')
- P += Inc;
- return P;
- }
-};
-
-string_view_pair separate_filename(string_view_t const & s) {
- if (s == "." || s == ".." || s.empty()) return string_view_pair{s, ""};
- auto pos = s.find_last_of('.');
- if (pos == string_view_t::npos || pos == 0)
- return string_view_pair{s, string_view_t{}};
- return string_view_pair{s.substr(0, pos), s.substr(pos)};
-}
-
-string_view_t createView(PosPtr S, PosPtr E) noexcept {
- return {S, static_cast<size_t>(E - S) + 1};
-}
-
-}} // namespace parser
-
-
-// POSIX HELPERS
-
-namespace detail { namespace {
-
-using value_type = path::value_type;
-using string_type = path::string_type;
-
-struct FileDescriptor {
- const path& name;
- int fd = -1;
- StatT m_stat;
- file_status m_status;
-
- template <class... Args>
- static FileDescriptor create(const path* p, error_code& ec, Args... args) {
- ec.clear();
- int fd;
- if ((fd = ::open(p->c_str(), args...)) == -1) {
- ec = capture_errno();
- return FileDescriptor{p};
- }
- return FileDescriptor(p, fd);
- }
-
- template <class... Args>
- static FileDescriptor create_with_status(const path* p, error_code& ec,
- Args... args) {
- FileDescriptor fd = create(p, ec, args...);
- if (!ec)
- fd.refresh_status(ec);
-
- return fd;
- }
-
- file_status get_status() const { return m_status; }
- StatT const& get_stat() const { return m_stat; }
-
- bool status_known() const { return _VSTD_FS::status_known(m_status); }
-
- file_status refresh_status(error_code& ec);
-
- void close() noexcept {
- if (fd != -1)
- ::close(fd);
- fd = -1;
- }
-
- FileDescriptor(FileDescriptor&& other)
- : name(other.name), fd(other.fd), m_stat(other.m_stat),
- m_status(other.m_status) {
- other.fd = -1;
- other.m_status = file_status{};
- }
-
- ~FileDescriptor() { close(); }
-
- FileDescriptor() = default;
- FileDescriptor(FileDescriptor const&) = delete;
- FileDescriptor& operator=(FileDescriptor const&) = delete;
-
-private:
- explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
-};
-
-perms posix_get_perms(const StatT& st) noexcept {
- return static_cast<perms>(st.st_mode) & perms::mask;
-}
-
-::mode_t posix_convert_perms(perms prms) {
- return static_cast< ::mode_t>(prms & perms::mask);
-}
-
-file_status create_file_status(error_code& m_ec, path const& p,
- const StatT& path_stat, error_code* ec) {
- if (ec)
- *ec = m_ec;
- if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
- return file_status(file_type::not_found);
- } else if (m_ec) {
- ErrorHandler<void> err("posix_stat", ec, &p);
- err.report(m_ec, "failed to determine attributes for the specified path");
- return file_status(file_type::none);
- }
- // else
-
- file_status fs_tmp;
- auto const mode = path_stat.st_mode;
- if (S_ISLNK(mode))
- fs_tmp.type(file_type::symlink);
- else if (S_ISREG(mode))
- fs_tmp.type(file_type::regular);
- else if (S_ISDIR(mode))
- fs_tmp.type(file_type::directory);
- else if (S_ISBLK(mode))
- fs_tmp.type(file_type::block);
- else if (S_ISCHR(mode))
- fs_tmp.type(file_type::character);
- else if (S_ISFIFO(mode))
- fs_tmp.type(file_type::fifo);
- else if (S_ISSOCK(mode))
- fs_tmp.type(file_type::socket);
- else
- fs_tmp.type(file_type::unknown);
-
- fs_tmp.permissions(detail::posix_get_perms(path_stat));
- return fs_tmp;
-}
-
-file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
- error_code m_ec;
- if (::stat(p.c_str(), &path_stat) == -1)
- m_ec = detail::capture_errno();
- return create_file_status(m_ec, p, path_stat, ec);
-}
-
-file_status posix_stat(path const& p, error_code* ec) {
- StatT path_stat;
- return posix_stat(p, path_stat, ec);
-}
-
-file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
- error_code m_ec;
- if (::lstat(p.c_str(), &path_stat) == -1)
- m_ec = detail::capture_errno();
- return create_file_status(m_ec, p, path_stat, ec);
-}
-
-file_status posix_lstat(path const& p, error_code* ec) {
- StatT path_stat;
- return posix_lstat(p, path_stat, ec);
-}
-
-bool posix_ftruncate(const FileDescriptor& fd, size_t to_size,
- error_code& ec) {
- if (::ftruncate(fd.fd, to_size) == -1) {
- ec = capture_errno();
- return true;
- }
- ec.clear();
- return false;
-}
-
-bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
- if (::fchmod(fd.fd, st.st_mode) == -1) {
- ec = capture_errno();
- return true;
- }
- ec.clear();
- return false;
-}
-
-bool stat_equivalent(const StatT& st1, const StatT& st2) {
- return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
-}
-
-file_status FileDescriptor::refresh_status(error_code& ec) {
- // FD must be open and good.
- m_status = file_status{};
- m_stat = {};
- error_code m_ec;
- if (::fstat(fd, &m_stat) == -1)
- m_ec = capture_errno();
- m_status = create_file_status(m_ec, name, m_stat, &ec);
- return m_status;
-}
-}} // end namespace detail
-
-using detail::capture_errno;
-using detail::ErrorHandler;
-using detail::StatT;
-using detail::TimeSpec;
-using parser::createView;
-using parser::PathParser;
-using parser::string_view_t;
-
-const bool _FilesystemClock::is_steady;
-
-_FilesystemClock::time_point _FilesystemClock::now() noexcept {
- typedef chrono::duration<rep> __secs;
-#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
- typedef chrono::duration<rep, nano> __nsecs;
- struct timespec tp;
- if (0 != clock_gettime(CLOCK_REALTIME, &tp))
- __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
- return time_point(__secs(tp.tv_sec) +
- chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
-#else
- typedef chrono::duration<rep, micro> __microsecs;
- timeval tv;
- gettimeofday(&tv, 0);
- return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
-#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
-}
-
-filesystem_error::~filesystem_error() {}
-
-void filesystem_error::__create_what(int __num_paths) {
- const char* derived_what = system_error::what();
- __storage_->__what_ = [&]() -> string {
- const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str();
- const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str();
- switch (__num_paths) {
- default:
- return detail::format_string("filesystem error: %s", derived_what);
- case 1:
- return detail::format_string("filesystem error: %s [%s]", derived_what,
- p1);
- case 2:
- return detail::format_string("filesystem error: %s [%s] [%s]",
- derived_what, p1, p2);
- }
- }();
-}
-
-static path __do_absolute(const path& p, path *cwd, error_code *ec) {
- if (ec) ec->clear();
- if (p.is_absolute())
- return p;
- *cwd = __current_path(ec);
- if (ec && *ec)
- return {};
- return (*cwd) / p;
-}
-
-path __absolute(const path& p, error_code *ec) {
- path cwd;
- return __do_absolute(p, &cwd, ec);
-}
-
-path __canonical(path const & orig_p, error_code *ec)
-{
- path cwd;
- ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
-
- path p = __do_absolute(orig_p, &cwd, ec);
- char buff[PATH_MAX + 1];
- char *ret;
- if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
- return err.report(capture_errno());
- return {ret};
-}
-
-void __copy(const path& from, const path& to, copy_options options,
- error_code *ec)
-{
- ErrorHandler<void> err("copy", ec, &from, &to);
-
- const bool sym_status = bool(
- options & (copy_options::create_symlinks | copy_options::skip_symlinks));
-
- const bool sym_status2 = bool(options & copy_options::copy_symlinks);
-
- error_code m_ec1;
- StatT f_st = {};
- const file_status f = sym_status || sym_status2
- ? detail::posix_lstat(from, f_st, &m_ec1)
- : detail::posix_stat(from, f_st, &m_ec1);
- if (m_ec1)
- return err.report(m_ec1);
-
- StatT t_st = {};
- const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
- : detail::posix_stat(to, t_st, &m_ec1);
-
- if (not status_known(t))
- return err.report(m_ec1);
-
- if (!exists(f) || is_other(f) || is_other(t) ||
- (is_directory(f) && is_regular_file(t)) ||
- detail::stat_equivalent(f_st, t_st)) {
- return err.report(errc::function_not_supported);
- }
-
- if (ec) ec->clear();
-
- if (is_symlink(f)) {
- if (bool(copy_options::skip_symlinks & options)) {
- // do nothing
- } else if (not exists(t)) {
- __copy_symlink(from, to, ec);
- } else {
- return err.report(errc::file_exists);
- }
- return;
- }
- else if (is_regular_file(f)) {
- if (bool(copy_options::directories_only & options)) {
- // do nothing
- }
- else if (bool(copy_options::create_symlinks & options)) {
- __create_symlink(from, to, ec);
- }
- else if (bool(copy_options::create_hard_links & options)) {
- __create_hard_link(from, to, ec);
- }
- else if (is_directory(t)) {
- __copy_file(from, to / from.filename(), options, ec);
- } else {
- __copy_file(from, to, options, ec);
- }
- return;
- }
- else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
- return err.report(errc::is_a_directory);
- }
- else if (is_directory(f) && (bool(copy_options::recursive & options) ||
- copy_options::none == options)) {
-
- if (!exists(t)) {
- // create directory to with attributes from 'from'.
- __create_directory(to, from, ec);
- if (ec && *ec) { return; }
- }
- directory_iterator it = ec ? directory_iterator(from, *ec)
- : directory_iterator(from);
- if (ec && *ec) { return; }
- error_code m_ec2;
- for (; it != directory_iterator(); it.increment(m_ec2)) {
- if (m_ec2) {
- return err.report(m_ec2);
- }
- __copy(it->path(), to / it->path().filename(),
- options | copy_options::__in_recursive_copy, ec);
- if (ec && *ec) { return; }
- }
- }
-}
-
-namespace detail {
-namespace {
-
-
-#ifdef _LIBCPP_USE_SENDFILE
-bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
- error_code& ec) {
-
- size_t count = read_fd.get_stat().st_size;
- do {
- ssize_t res;
- if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
- ec = capture_errno();
- return false;
- }
- count -= res;
- } while (count > 0);
-
- ec.clear();
-
- return true;
-}
-#elif defined(_LIBCPP_USE_COPYFILE)
-bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
- error_code& ec) {
- struct CopyFileState {
- copyfile_state_t state;
- CopyFileState() { state = copyfile_state_alloc(); }
- ~CopyFileState() { copyfile_state_free(state); }
-
- private:
- CopyFileState(CopyFileState const&) = delete;
- CopyFileState& operator=(CopyFileState const&) = delete;
- };
-
- CopyFileState cfs;
- if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
- ec = capture_errno();
- return false;
- }
-
- ec.clear();
- return true;
-}
-#endif
-
-// Note: This function isn't guarded by ifdef's even though it may be unused
-// in order to assure it still compiles.
-__attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd,
- FileDescriptor& write_fd,
- error_code& ec) {
- ifstream in;
- in.__open(read_fd.fd, ios::binary);
- if (!in.is_open()) {
- // This assumes that __open didn't reset the error code.
- ec = capture_errno();
- return false;
- }
- ofstream out;
- out.__open(write_fd.fd, ios::binary);
- if (!out.is_open()) {
- ec = capture_errno();
- return false;
- }
-
- if (in.good() && out.good()) {
- using InIt = istreambuf_iterator<char>;
- using OutIt = ostreambuf_iterator<char>;
- InIt bin(in);
- InIt ein;
- OutIt bout(out);
- copy(bin, ein, bout);
- }
- if (out.fail() || in.fail()) {
- ec = make_error_code(errc::io_error);
- return false;
- }
-
- ec.clear();
- return true;
-}
-
-bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) {
-#if defined(_LIBCPP_USE_SENDFILE)
- return copy_file_impl_sendfile(from, to, ec);
-#elif defined(_LIBCPP_USE_COPYFILE)
- return copy_file_impl_copyfile(from, to, ec);
-#else
- return copy_file_impl_default(from, to, ec);
-#endif
-}
-
-} // namespace
-} // namespace detail
-
-bool __copy_file(const path& from, const path& to, copy_options options,
- error_code *ec)
-{
- using detail::FileDescriptor;
- ErrorHandler<bool> err("copy_file", ec, &to, &from);
-
- error_code m_ec;
- FileDescriptor from_fd =
- FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK);
- if (m_ec)
- return err.report(m_ec);
-
- auto from_st = from_fd.get_status();
- StatT const& from_stat = from_fd.get_stat();
- if (!is_regular_file(from_st)) {
- if (not m_ec)
- m_ec = make_error_code(errc::not_supported);
- return err.report(m_ec);
- }
-
- const bool skip_existing = bool(copy_options::skip_existing & options);
- const bool update_existing = bool(copy_options::update_existing & options);
- const bool overwrite_existing =
- bool(copy_options::overwrite_existing & options);
-
- StatT to_stat_path;
- file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
- if (!status_known(to_st))
- return err.report(m_ec);
-
- const bool to_exists = exists(to_st);
- if (to_exists && !is_regular_file(to_st))
- return err.report(errc::not_supported);
-
- if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
- return err.report(errc::file_exists);
-
- if (to_exists && skip_existing)
- return false;
-
- bool ShouldCopy = [&]() {
- if (to_exists && update_existing) {
- auto from_time = detail::extract_mtime(from_stat);
- auto to_time = detail::extract_mtime(to_stat_path);
- if (from_time.tv_sec < to_time.tv_sec)
- return false;
- if (from_time.tv_sec == to_time.tv_sec &&
- from_time.tv_nsec <= to_time.tv_nsec)
- return false;
- return true;
- }
- if (!to_exists || overwrite_existing)
- return true;
- return err.report(errc::file_exists);
- }();
- if (!ShouldCopy)
- return false;
-
- // Don't truncate right away. We may not be opening the file we originally
- // looked at; we'll check this later.
- int to_open_flags = O_WRONLY;
- if (!to_exists)
- to_open_flags |= O_CREAT;
- FileDescriptor to_fd = FileDescriptor::create_with_status(
- &to, m_ec, to_open_flags, from_stat.st_mode);
- if (m_ec)
- return err.report(m_ec);
-
- if (to_exists) {
- // Check that the file we initially stat'ed is equivalent to the one
- // we opened.
- // FIXME: report this better.
- if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
- return err.report(errc::bad_file_descriptor);
-
- // Set the permissions and truncate the file we opened.
- if (detail::posix_fchmod(to_fd, from_stat, m_ec))
- return err.report(m_ec);
- if (detail::posix_ftruncate(to_fd, 0, m_ec))
- return err.report(m_ec);
- }
-
- if (!copy_file_impl(from_fd, to_fd, m_ec)) {
- // FIXME: Remove the dest file if we failed, and it didn't exist previously.
- return err.report(m_ec);
- }
-
- return true;
-}
-
-void __copy_symlink(const path& existing_symlink, const path& new_symlink,
- error_code *ec)
-{
- const path real_path(__read_symlink(existing_symlink, ec));
- if (ec && *ec) { return; }
- // NOTE: proposal says you should detect if you should call
- // create_symlink or create_directory_symlink. I don't think this
- // is needed with POSIX
- __create_symlink(real_path, new_symlink, ec);
-}
-
-bool __create_directories(const path& p, error_code *ec)
-{
- ErrorHandler<bool> err("create_directories", ec, &p);
-
- error_code m_ec;
- auto const st = detail::posix_stat(p, &m_ec);
- if (!status_known(st))
- return err.report(m_ec);
- else if (is_directory(st))
- return false;
- else if (exists(st))
- return err.report(errc::file_exists);
-
- const path parent = p.parent_path();
- if (!parent.empty()) {
- const file_status parent_st = status(parent, m_ec);
- if (not status_known(parent_st))
- return err.report(m_ec);
- if (not exists(parent_st)) {
- __create_directories(parent, ec);
- if (ec && *ec) {
- return false;
- }
- }
- }
- return __create_directory(p, ec);
-}
-
-bool __create_directory(const path& p, error_code *ec)
-{
- ErrorHandler<bool> err("create_directory", ec, &p);
-
- if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
- return true;
- if (errno != EEXIST)
- err.report(capture_errno());
- return false;
-}
-
-bool __create_directory(path const & p, path const & attributes,
- error_code *ec)
-{
- ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
-
- StatT attr_stat;
- error_code mec;
- auto st = detail::posix_stat(attributes, attr_stat, &mec);
- if (!status_known(st))
- return err.report(mec);
- if (!is_directory(st))
- return err.report(errc::not_a_directory, "the specified attribute path is invalid");
-
- if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
- return true;
- if (errno != EEXIST)
- err.report(capture_errno());
- return false;
-}
-
-void __create_directory_symlink(path const& from, path const& to,
- error_code* ec) {
- ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
- if (::symlink(from.c_str(), to.c_str()) != 0)
- return err.report(capture_errno());
-}
-
-void __create_hard_link(const path& from, const path& to, error_code *ec){
- ErrorHandler<void> err("create_hard_link", ec, &from, &to);
- if (::link(from.c_str(), to.c_str()) == -1)
- return err.report(capture_errno());
-}
-
-void __create_symlink(path const & from, path const & to, error_code *ec) {
- ErrorHandler<void> err("create_symlink", ec, &from, &to);
- if (::symlink(from.c_str(), to.c_str()) == -1)
- return err.report(capture_errno());
-}
-
-path __current_path(error_code *ec) {
- ErrorHandler<path> err("current_path", ec);
-
- auto size = ::pathconf(".", _PC_PATH_MAX);
- _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
-
- auto buff = unique_ptr<char[]>(new char[size + 1]);
- char* ret;
- if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr)
- return err.report(capture_errno(), "call to getcwd failed");
-
- return {buff.get()};
-}
-
-void __current_path(const path& p, error_code *ec) {
- ErrorHandler<void> err("current_path", ec, &p);
- if (::chdir(p.c_str()) == -1)
- err.report(capture_errno());
-}
-
-bool __equivalent(const path& p1, const path& p2, error_code *ec)
-{
- ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
-
- error_code ec1, ec2;
- StatT st1 = {}, st2 = {};
- auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
- if (!exists(s1))
- return err.report(errc::not_supported);
- auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
- if (!exists(s2))
- return err.report(errc::not_supported);
-
- return detail::stat_equivalent(st1, st2);
-}
-
-
-uintmax_t __file_size(const path& p, error_code *ec)
-{
- ErrorHandler<uintmax_t> err("file_size", ec, &p);
-
- error_code m_ec;
- StatT st;
- file_status fst = detail::posix_stat(p, st, &m_ec);
- if (!exists(fst) || !is_regular_file(fst)) {
- errc error_kind =
- is_directory(fst) ? errc::is_a_directory : errc::not_supported;
- if (!m_ec)
- m_ec = make_error_code(error_kind);
- return err.report(m_ec);
- }
- // is_regular_file(p) == true
- return static_cast<uintmax_t>(st.st_size);
-}
-
-uintmax_t __hard_link_count(const path& p, error_code *ec)
-{
- ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
-
- error_code m_ec;
- StatT st;
- detail::posix_stat(p, st, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- return static_cast<uintmax_t>(st.st_nlink);
-}
-
-
-bool __fs_is_empty(const path& p, error_code *ec)
-{
- ErrorHandler<bool> err("is_empty", ec, &p);
-
- error_code m_ec;
- StatT pst;
- auto st = detail::posix_stat(p, pst, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- else if (!is_directory(st) && !is_regular_file(st))
- return err.report(errc::not_supported);
- else if (is_directory(st)) {
- auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
- if (ec && *ec)
- return false;
- return it == directory_iterator{};
- } else if (is_regular_file(st))
- return static_cast<uintmax_t>(pst.st_size) == 0;
-
- _LIBCPP_UNREACHABLE();
-}
-
-static file_time_type __extract_last_write_time(const path& p, const StatT& st,
- error_code* ec) {
- using detail::fs_time;
- ErrorHandler<file_time_type> err("last_write_time", ec, &p);
-
- auto ts = detail::extract_mtime(st);
- if (!fs_time::is_representable(ts))
- return err.report(errc::value_too_large);
-
- return fs_time::convert_from_timespec(ts);
-}
-
-file_time_type __last_write_time(const path& p, error_code *ec)
-{
- using namespace chrono;
- ErrorHandler<file_time_type> err("last_write_time", ec, &p);
-
- error_code m_ec;
- StatT st;
- detail::posix_stat(p, st, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- return __extract_last_write_time(p, st, ec);
-}
-
-void __last_write_time(const path& p, file_time_type new_time,
- error_code *ec)
-{
- using detail::fs_time;
- ErrorHandler<void> err("last_write_time", ec, &p);
-
- error_code m_ec;
- array<TimeSpec, 2> tbuf;
-#if !defined(_LIBCPP_USE_UTIMENSAT)
- // This implementation has a race condition between determining the
- // last access time and attempting to set it to the same value using
- // ::utimes
- StatT st;
- file_status fst = detail::posix_stat(p, st, &m_ec);
- if (m_ec)
- return err.report(m_ec);
- tbuf[0] = detail::extract_atime(st);
-#else
- tbuf[0].tv_sec = 0;
- tbuf[0].tv_nsec = UTIME_OMIT;
-#endif
- if (!fs_time::convert_to_timespec(tbuf[1], new_time))
- return err.report(errc::value_too_large);
-
- detail::set_file_times(p, tbuf, m_ec);
- if (m_ec)
- return err.report(m_ec);
-}
-
-
-void __permissions(const path& p, perms prms, perm_options opts,
- error_code *ec)
-{
- ErrorHandler<void> err("permissions", ec, &p);
-
- auto has_opt = [&](perm_options o) { return bool(o & opts); };
- const bool resolve_symlinks = !has_opt(perm_options::nofollow);
- const bool add_perms = has_opt(perm_options::add);
- const bool remove_perms = has_opt(perm_options::remove);
- _LIBCPP_ASSERT(
- (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
- "One and only one of the perm_options constants replace, add, or remove "
- "is present in opts");
-
- bool set_sym_perms = false;
- prms &= perms::mask;
- if (!resolve_symlinks || (add_perms || remove_perms)) {
- error_code m_ec;
- file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
- : detail::posix_lstat(p, &m_ec);
- set_sym_perms = is_symlink(st);
- if (m_ec)
- return err.report(m_ec);
- _LIBCPP_ASSERT(st.permissions() != perms::unknown,
- "Permissions unexpectedly unknown");
- if (add_perms)
- prms |= st.permissions();
- else if (remove_perms)
- prms = st.permissions() & ~prms;
- }
- const auto real_perms = detail::posix_convert_perms(prms);
-
-# if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
- const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
- if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
- return err.report(capture_errno());
- }
-# else
- if (set_sym_perms)
- return err.report(errc::operation_not_supported);
- if (::chmod(p.c_str(), real_perms) == -1) {
- return err.report(capture_errno());
- }
-# endif
-}
-
-
-path __read_symlink(const path& p, error_code *ec) {
- ErrorHandler<path> err("read_symlink", ec, &p);
-
- char buff[PATH_MAX + 1];
- error_code m_ec;
- ::ssize_t ret;
- if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
- return err.report(capture_errno());
- }
- _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
- _LIBCPP_ASSERT(ret > 0, "TODO");
- buff[ret] = 0;
- return {buff};
-}
-
-
-bool __remove(const path& p, error_code *ec) {
- ErrorHandler<bool> err("remove", ec, &p);
- if (::remove(p.c_str()) == -1) {
- if (errno != ENOENT)
- err.report(capture_errno());
- return false;
- }
- return true;
-}
-
-namespace {
-
-uintmax_t remove_all_impl(path const & p, error_code& ec)
-{
- const auto npos = static_cast<uintmax_t>(-1);
- const file_status st = __symlink_status(p, &ec);
- if (ec) return npos;
- uintmax_t count = 1;
- if (is_directory(st)) {
- for (directory_iterator it(p, ec); !ec && it != directory_iterator();
- it.increment(ec)) {
- auto other_count = remove_all_impl(it->path(), ec);
- if (ec) return npos;
- count += other_count;
- }
- if (ec) return npos;
- }
- if (!__remove(p, &ec)) return npos;
- return count;
-}
-
-} // end namespace
-
-uintmax_t __remove_all(const path& p, error_code *ec) {
- ErrorHandler<uintmax_t> err("remove_all", ec, &p);
-
- error_code mec;
- auto count = remove_all_impl(p, mec);
- if (mec) {
- if (mec == errc::no_such_file_or_directory)
- return 0;
- return err.report(mec);
- }
- return count;
-}
-
-void __rename(const path& from, const path& to, error_code *ec) {
- ErrorHandler<void> err("rename", ec, &from, &to);
- if (::rename(from.c_str(), to.c_str()) == -1)
- err.report(capture_errno());
-}
-
-void __resize_file(const path& p, uintmax_t size, error_code *ec) {
- ErrorHandler<void> err("resize_file", ec, &p);
- if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
- return err.report(capture_errno());
-}
-
-space_info __space(const path& p, error_code *ec) {
- ErrorHandler<void> err("space", ec, &p);
- space_info si;
- struct statvfs m_svfs = {};
- if (::statvfs(p.c_str(), &m_svfs) == -1) {
- err.report(capture_errno());
- si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
- return si;
- }
- // Multiply with overflow checking.
- auto do_mult = [&](uintmax_t& out, uintmax_t other) {
- out = other * m_svfs.f_frsize;
- if (other == 0 || out / other != m_svfs.f_frsize)
- out = static_cast<uintmax_t>(-1);
- };
- do_mult(si.capacity, m_svfs.f_blocks);
- do_mult(si.free, m_svfs.f_bfree);
- do_mult(si.available, m_svfs.f_bavail);
- return si;
-}
-
-file_status __status(const path& p, error_code *ec) {
- return detail::posix_stat(p, ec);
-}
-
-file_status __symlink_status(const path& p, error_code *ec) {
- return detail::posix_lstat(p, ec);
-}
-
-path __temp_directory_path(error_code* ec) {
- ErrorHandler<path> err("temp_directory_path", ec);
-
- const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
- const char* ret = nullptr;
-
- for (auto& ep : env_paths)
- if ((ret = getenv(ep)))
- break;
- if (ret == nullptr)
- ret = "/tmp";
-
- path p(ret);
- error_code m_ec;
- file_status st = detail::posix_stat(p, &m_ec);
- if (!status_known(st))
- return err.report(m_ec, "cannot access path \"%s\"", p);
-
- if (!exists(st) || !is_directory(st))
- return err.report(errc::not_a_directory, "path \"%s\" is not a directory",
- p);
-
- return p;
-}
-
-
-path __weakly_canonical(const path& p, error_code *ec) {
- ErrorHandler<path> err("weakly_canonical", ec, &p);
-
- if (p.empty())
- return __canonical("", ec);
-
- path result;
- path tmp;
- tmp.__reserve(p.native().size());
- auto PP = PathParser::CreateEnd(p.native());
- --PP;
- vector<string_view_t> DNEParts;
-
- while (PP.State != PathParser::PS_BeforeBegin) {
- tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
- error_code m_ec;
- file_status st = __status(tmp, &m_ec);
- if (!status_known(st)) {
- return err.report(m_ec);
- } else if (exists(st)) {
- result = __canonical(tmp, ec);
- break;
- }
- DNEParts.push_back(*PP);
- --PP;
- }
- if (PP.State == PathParser::PS_BeforeBegin)
- result = __canonical("", ec);
- if (ec) ec->clear();
- if (DNEParts.empty())
- return result;
- for (auto It=DNEParts.rbegin(); It != DNEParts.rend(); ++It)
- result /= *It;
- return result.lexically_normal();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// path definitions
-///////////////////////////////////////////////////////////////////////////////
-
-constexpr path::value_type path::preferred_separator;
-
-path & path::replace_extension(path const & replacement)
-{
- path p = extension();
- if (not p.empty()) {
- __pn_.erase(__pn_.size() - p.native().size());
- }
- if (!replacement.empty()) {
- if (replacement.native()[0] != '.') {
- __pn_ += ".";
- }
- __pn_.append(replacement.__pn_);
- }
- return *this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// path.decompose
-
-string_view_t path::__root_name() const
-{
- auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName)
- return *PP;
- return {};
-}
-
-string_view_t path::__root_directory() const
-{
- auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName)
- ++PP;
- if (PP.State == PathParser::PS_InRootDir)
- return *PP;
- return {};
-}
-
-string_view_t path::__root_path_raw() const
-{
- auto PP = PathParser::CreateBegin(__pn_);
- if (PP.State == PathParser::PS_InRootName) {
- auto NextCh = PP.peek();
- if (NextCh && *NextCh == '/') {
- ++PP;
- return createView(__pn_.data(), &PP.RawEntry.back());
- }
- return PP.RawEntry;
- }
- if (PP.State == PathParser::PS_InRootDir)
- return *PP;
- return {};
-}
-
-static bool ConsumeRootDir(PathParser* PP) {
- while (PP->State <= PathParser::PS_InRootDir)
- ++(*PP);
- return PP->State == PathParser::PS_AtEnd;
-}
-
-string_view_t path::__relative_path() const
-{
- auto PP = PathParser::CreateBegin(__pn_);
- if (ConsumeRootDir(&PP))
- return {};
- return createView(PP.RawEntry.data(), &__pn_.back());
-}
-
-string_view_t path::__parent_path() const
-{
- if (empty())
- return {};
- // Determine if we have a root path but not a relative path. In that case
- // return *this.
- {
- auto PP = PathParser::CreateBegin(__pn_);
- if (ConsumeRootDir(&PP))
- return __pn_;
- }
- // Otherwise remove a single element from the end of the path, and return
- // a string representing that path
- {
- auto PP = PathParser::CreateEnd(__pn_);
- --PP;
- if (PP.RawEntry.data() == __pn_.data())
- return {};
- --PP;
- return createView(__pn_.data(), &PP.RawEntry.back());
- }
-}
-
-string_view_t path::__filename() const
-{
- if (empty()) return {};
- {
- PathParser PP = PathParser::CreateBegin(__pn_);
- if (ConsumeRootDir(&PP))
- return {};
- }
- return *(--PathParser::CreateEnd(__pn_));
-}
-
-string_view_t path::__stem() const
-{
- return parser::separate_filename(__filename()).first;
-}
-
-string_view_t path::__extension() const
-{
- return parser::separate_filename(__filename()).second;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.gen
-
-
-enum PathPartKind : unsigned char {
- PK_None,
- PK_RootSep,
- PK_Filename,
- PK_Dot,
- PK_DotDot,
- PK_TrailingSep
-};
-
-static PathPartKind ClassifyPathPart(string_view_t Part) {
- if (Part.empty())
- return PK_TrailingSep;
- if (Part == ".")
- return PK_Dot;
- if (Part == "..")
- return PK_DotDot;
- if (Part == "/")
- return PK_RootSep;
- return PK_Filename;
-}
-
-path path::lexically_normal() const {
- if (__pn_.empty())
- return *this;
-
- using PartKindPair = pair<string_view_t, PathPartKind>;
- vector<PartKindPair> Parts;
- // Guess as to how many elements the path has to avoid reallocating.
- Parts.reserve(32);
-
- // Track the total size of the parts as we collect them. This allows the
- // resulting path to reserve the correct amount of memory.
- size_t NewPathSize = 0;
- auto AddPart = [&](PathPartKind K, string_view_t P) {
- NewPathSize += P.size();
- Parts.emplace_back(P, K);
- };
- auto LastPartKind = [&]() {
- if (Parts.empty())
- return PK_None;
- return Parts.back().second;
- };
-
- bool MaybeNeedTrailingSep = false;
- // Build a stack containing the remaining elements of the path, popping off
- // elements which occur before a '..' entry.
- for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
- auto Part = *PP;
- PathPartKind Kind = ClassifyPathPart(Part);
- switch (Kind) {
- case PK_Filename:
- case PK_RootSep: {
- // Add all non-dot and non-dot-dot elements to the stack of elements.
- AddPart(Kind, Part);
- MaybeNeedTrailingSep = false;
- break;
- }
- case PK_DotDot: {
- // Only push a ".." element if there are no elements preceding the "..",
- // or if the preceding element is itself "..".
- auto LastKind = LastPartKind();
- if (LastKind == PK_Filename) {
- NewPathSize -= Parts.back().first.size();
- Parts.pop_back();
- } else if (LastKind != PK_RootSep)
- AddPart(PK_DotDot, "..");
- MaybeNeedTrailingSep = LastKind == PK_Filename;
- break;
- }
- case PK_Dot:
- case PK_TrailingSep: {
- MaybeNeedTrailingSep = true;
- break;
- }
- case PK_None:
- _LIBCPP_UNREACHABLE();
- }
- }
- // [fs.path.generic]p6.8: If the path is empty, add a dot.
- if (Parts.empty())
- return ".";
-
- // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
- // trailing directory-separator.
- bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
-
- path Result;
- Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
- for (auto &PK : Parts)
- Result /= PK.first;
-
- if (NeedTrailingSep)
- Result /= "";
-
- return Result;
-}
-
-static int DetermineLexicalElementCount(PathParser PP) {
- int Count = 0;
- for (; PP; ++PP) {
- auto Elem = *PP;
- if (Elem == "..")
- --Count;
- else if (Elem != ".")
- ++Count;
- }
- return Count;
-}
-
-path path::lexically_relative(const path& base) const {
- { // perform root-name/root-directory mismatch checks
- auto PP = PathParser::CreateBegin(__pn_);
- auto PPBase = PathParser::CreateBegin(base.__pn_);
- auto CheckIterMismatchAtBase = [&]() {
- return PP.State != PPBase.State && (
- PP.inRootPath() || PPBase.inRootPath());
- };
- if (PP.State == PathParser::PS_InRootName &&
- PPBase.State == PathParser::PS_InRootName) {
- if (*PP != *PPBase)
- return {};
- } else if (CheckIterMismatchAtBase())
- return {};
-
- if (PP.inRootPath()) ++PP;
- if (PPBase.inRootPath()) ++PPBase;
- if (CheckIterMismatchAtBase())
- return {};
- }
-
- // Find the first mismatching element
- auto PP = PathParser::CreateBegin(__pn_);
- auto PPBase = PathParser::CreateBegin(base.__pn_);
- while (PP && PPBase && PP.State == PPBase.State &&
- *PP == *PPBase) {
- ++PP;
- ++PPBase;
- }
-
- // If there is no mismatch, return ".".
- if (!PP && !PPBase)
- return ".";
-
- // Otherwise, determine the number of elements, 'n', which are not dot or
- // dot-dot minus the number of dot-dot elements.
- int ElemCount = DetermineLexicalElementCount(PPBase);
- if (ElemCount < 0)
- return {};
-
- // return a path constructed with 'n' dot-dot elements, followed by the the
- // elements of '*this' after the mismatch.
- path Result;
- // FIXME: Reserve enough room in Result that it won't have to re-allocate.
- while (ElemCount--)
- Result /= "..";
- for (; PP; ++PP)
- Result /= *PP;
- return Result;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.comparisons
-int path::__compare(string_view_t __s) const {
- auto PP = PathParser::CreateBegin(__pn_);
- auto PP2 = PathParser::CreateBegin(__s);
- while (PP && PP2) {
- int res = (*PP).compare(*PP2);
- if (res != 0) return res;
- ++PP; ++PP2;
- }
- if (PP.State == PP2.State && !PP)
- return 0;
- if (!PP)
- return -1;
- return 1;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.nonmembers
-size_t hash_value(const path& __p) noexcept {
- auto PP = PathParser::CreateBegin(__p.native());
- size_t hash_value = 0;
- hash<string_view_t> hasher;
- while (PP) {
- hash_value = __hash_combine(hash_value, hasher(*PP));
- ++PP;
- }
- return hash_value;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// path.itr
-path::iterator path::begin() const
-{
- auto PP = PathParser::CreateBegin(__pn_);
- iterator it;
- it.__path_ptr_ = this;
- it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
- it.__entry_ = PP.RawEntry;
- it.__stashed_elem_.__assign_view(*PP);
- return it;
-}
-
-path::iterator path::end() const
-{
- iterator it{};
- it.__state_ = path::iterator::_AtEnd;
- it.__path_ptr_ = this;
- return it;
-}
-
-path::iterator& path::iterator::__increment() {
- PathParser PP(__path_ptr_->native(), __entry_, __state_);
- ++PP;
- __state_ = static_cast<_ParserState>(PP.State);
- __entry_ = PP.RawEntry;
- __stashed_elem_.__assign_view(*PP);
- return *this;
-}
-
-path::iterator& path::iterator::__decrement() {
- PathParser PP(__path_ptr_->native(), __entry_, __state_);
- --PP;
- __state_ = static_cast<_ParserState>(PP.State);
- __entry_ = PP.RawEntry;
- __stashed_elem_.__assign_view(*PP);
- return *this;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// directory entry definitions
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _LIBCPP_WIN32API
-error_code directory_entry::__do_refresh() noexcept {
- __data_.__reset();
- error_code failure_ec;
-
- StatT full_st;
- file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
- if (!status_known(st)) {
- __data_.__reset();
- return failure_ec;
- }
-
- if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
- } else { // we have a symlink
- __data_.__sym_perms_ = st.permissions();
- // Get the information about the linked entity.
- // Ignore errors from stat, since we don't want errors regarding symlink
- // resolution to be reported to the user.
- error_code ignored_ec;
- st = detail::posix_stat(__p_, full_st, &ignored_ec);
-
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
-
- // If we failed to resolve the link, then only partially populate the
- // cache.
- if (!status_known(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
- return error_code{};
- }
- // Otherwise, we resolved the link, potentially as not existing.
- // That's OK.
- __data_.__cache_type_ = directory_entry::_RefreshSymlink;
- }
-
- if (_VSTD_FS::is_regular_file(st))
- __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
-
- if (_VSTD_FS::exists(st)) {
- __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
-
- // Attempt to extract the mtime, and fail if it's not representable using
- // file_time_type. For now we ignore the error, as we'll report it when
- // the value is actually used.
- error_code ignored_ec;
- __data_.__write_time_ =
- __extract_last_write_time(__p_, full_st, &ignored_ec);
- }
-
- return failure_ec;
-}
-#else
-error_code directory_entry::__do_refresh() noexcept {
- __data_.__reset();
- error_code failure_ec;
-
- file_status st = _VSTD_FS::symlink_status(__p_, failure_ec);
- if (!status_known(st)) {
- __data_.__reset();
- return failure_ec;
- }
-
- if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
- } else { // we have a symlink
- __data_.__sym_perms_ = st.permissions();
- // Get the information about the linked entity.
- // Ignore errors from stat, since we don't want errors regarding symlink
- // resolution to be reported to the user.
- error_code ignored_ec;
- st = _VSTD_FS::status(__p_, ignored_ec);
-
- __data_.__type_ = st.type();
- __data_.__non_sym_perms_ = st.permissions();
-
- // If we failed to resolve the link, then only partially populate the
- // cache.
- if (!status_known(st)) {
- __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
- return error_code{};
- }
- __data_.__cache_type_ = directory_entry::_RefreshSymlink;
- }
-
- // FIXME: This is currently broken, and the implementation only a placeholder.
- // We need to cache last_write_time, file_size, and hard_link_count here before
- // the implementation actually works.
-
- return failure_ec;
-}
-#endif
-
-_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM
--- /dev/null
+//===------------------ directory_iterator.cpp ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "filesystem"
+#include "__config"
+#if defined(_LIBCPP_WIN32API)
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#else
+#include <dirent.h>
+#endif
+#include <errno.h>
+
+#include "filesystem_common.h"
+
+_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
+
+namespace detail {
+namespace {
+
+#if !defined(_LIBCPP_WIN32API)
+template <class DirEntT, class = decltype(DirEntT::d_type)>
+static file_type get_file_type(DirEntT* ent, int) {
+ switch (ent->d_type) {
+ case DT_BLK:
+ return file_type::block;
+ case DT_CHR:
+ return file_type::character;
+ case DT_DIR:
+ return file_type::directory;
+ case DT_FIFO:
+ return file_type::fifo;
+ case DT_LNK:
+ return file_type::symlink;
+ case DT_REG:
+ return file_type::regular;
+ case DT_SOCK:
+ return file_type::socket;
+ // Unlike in lstat, hitting "unknown" here simply means that the underlying
+ // filesystem doesn't support d_type. Report is as 'none' so we correctly
+ // set the cache to empty.
+ case DT_UNKNOWN:
+ break;
+ }
+ return file_type::none;
+}
+
+template <class DirEntT>
+static file_type get_file_type(DirEntT* ent, long) {
+ return file_type::none;
+}
+
+static pair<string_view, file_type> posix_readdir(DIR* dir_stream,
+ error_code& ec) {
+ struct dirent* dir_entry_ptr = nullptr;
+ errno = 0; // zero errno in order to detect errors
+ ec.clear();
+ if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) {
+ if (errno)
+ ec = capture_errno();
+ return {};
+ } else {
+ return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)};
+ }
+}
+#else
+
+static file_type get_file_type(const WIN32_FIND_DATA& data) {
+ //auto attrs = data.dwFileAttributes;
+ // FIXME(EricWF)
+ return file_type::unknown;
+}
+static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
+ return (data.nFileSizeHight * (MAXDWORD + 1)) + data.nFileSizeLow;
+}
+static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
+ ULARGE_INTEGER tmp;
+ FILETIME& time = data.ftLastWriteTime;
+ tmp.u.LowPart = time.dwLowDateTime;
+ tmp.u.HighPart = time.dwHighDateTime;
+ return file_time_type(file_time_type::duration(time.QuadPart));
+}
+
+#endif
+
+} // namespace
+} // namespace detail
+
+using detail::ErrorHandler;
+
+#if defined(_LIBCPP_WIN32API)
+class __dir_stream {
+public:
+ __dir_stream() = delete;
+ __dir_stream& operator=(const __dir_stream&) = delete;
+
+ __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_),
+ __root_(move(__ds.__root_)),
+ __entry_(move(__ds.__entry_)) {
+ __ds.__stream_ = INVALID_HANDLE_VALUE;
+ }
+
+ __dir_stream(const path& root, directory_options opts, error_code& ec)
+ : __stream_(INVALID_HANDLE_VALUE), __root_(root) {
+ __stream_ = ::FindFirstFileEx(root.c_str(), &__data_);
+ if (__stream_ == INVALID_HANDLE_VALUE) {
+ ec = error_code(::GetLastError(), generic_category());
+ const bool ignore_permission_denied =
+ bool(opts & directory_options::skip_permission_denied);
+ if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
+ ec.clear();
+ return;
+ }
+ }
+
+ ~__dir_stream() noexcept {
+ if (__stream_ == INVALID_HANDLE_VALUE)
+ return;
+ close();
+ }
+
+ bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }
+
+ bool advance(error_code& ec) {
+ while (::FindNextFile(__stream_, &__data_)) {
+ if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
+ continue;
+ // FIXME: Cache more of this
+ //directory_entry::__cached_data cdata;
+ //cdata.__type_ = get_file_type(__data_);
+ //cdata.__size_ = get_file_size(__data_);
+ //cdata.__write_time_ = get_write_time(__data_);
+ __entry_.__assign_iter_entry(
+ __root_ / __data_.cFileName,
+ directory_entry::__create_iter_result(get_file_type(__data)));
+ return true;
+ }
+ ec = error_code(::GetLastError(), generic_category());
+ close();
+ return false;
+ }
+
+private:
+ error_code close() noexcept {
+ error_code ec;
+ if (!::FindClose(__stream_))
+ ec = error_code(::GetLastError(), generic_category());
+ __stream_ = INVALID_HANDLE_VALUE;
+ return ec;
+ }
+
+ HANDLE __stream_{INVALID_HANDLE_VALUE};
+ WIN32_FIND_DATA __data_;
+
+public:
+ path __root_;
+ directory_entry __entry_;
+};
+#else
+class __dir_stream {
+public:
+ __dir_stream() = delete;
+ __dir_stream& operator=(const __dir_stream&) = delete;
+
+ __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_),
+ __root_(move(other.__root_)),
+ __entry_(move(other.__entry_)) {
+ other.__stream_ = nullptr;
+ }
+
+ __dir_stream(const path& root, directory_options opts, error_code& ec)
+ : __stream_(nullptr), __root_(root) {
+ if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
+ ec = detail::capture_errno();
+ const bool allow_eacess =
+ bool(opts & directory_options::skip_permission_denied);
+ if (allow_eacess && ec.value() == EACCES)
+ ec.clear();
+ return;
+ }
+ advance(ec);
+ }
+
+ ~__dir_stream() noexcept {
+ if (__stream_)
+ close();
+ }
+
+ bool good() const noexcept { return __stream_ != nullptr; }
+
+ bool advance(error_code& ec) {
+ while (true) {
+ auto str_type_pair = detail::posix_readdir(__stream_, ec);
+ auto& str = str_type_pair.first;
+ if (str == "." || str == "..") {
+ continue;
+ } else if (ec || str.empty()) {
+ close();
+ return false;
+ } else {
+ __entry_.__assign_iter_entry(
+ __root_ / str,
+ directory_entry::__create_iter_result(str_type_pair.second));
+ return true;
+ }
+ }
+ }
+
+private:
+ error_code close() noexcept {
+ error_code m_ec;
+ if (::closedir(__stream_) == -1)
+ m_ec = detail::capture_errno();
+ __stream_ = nullptr;
+ return m_ec;
+ }
+
+ DIR* __stream_{nullptr};
+
+public:
+ path __root_;
+ directory_entry __entry_;
+};
+#endif
+
+// directory_iterator
+
+directory_iterator::directory_iterator(const path& p, error_code* ec,
+ directory_options opts) {
+ ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p);
+
+ error_code m_ec;
+ __imp_ = make_shared<__dir_stream>(p, opts, m_ec);
+ if (ec)
+ *ec = m_ec;
+ if (!__imp_->good()) {
+ __imp_.reset();
+ if (m_ec)
+ err.report(m_ec);
+ }
+}
+
+directory_iterator& directory_iterator::__increment(error_code* ec) {
+ _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
+ ErrorHandler<void> err("directory_iterator::operator++()", ec);
+
+ error_code m_ec;
+ if (!__imp_->advance(m_ec)) {
+ path root = move(__imp_->__root_);
+ __imp_.reset();
+ if (m_ec)
+ err.report(m_ec, "at root \"%s\"", root);
+ }
+ return *this;
+}
+
+directory_entry const& directory_iterator::__dereference() const {
+ _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
+ return __imp_->__entry_;
+}
+
+// recursive_directory_iterator
+
+struct recursive_directory_iterator::__shared_imp {
+ stack<__dir_stream> __stack_;
+ directory_options __options_;
+};
+
+recursive_directory_iterator::recursive_directory_iterator(
+ const path& p, directory_options opt, error_code* ec)
+ : __imp_(nullptr), __rec_(true) {
+ ErrorHandler<void> err("recursive_directory_iterator", ec, &p);
+
+ error_code m_ec;
+ __dir_stream new_s(p, opt, m_ec);
+ if (m_ec)
+ err.report(m_ec);
+ if (m_ec || !new_s.good())
+ return;
+
+ __imp_ = make_shared<__shared_imp>();
+ __imp_->__options_ = opt;
+ __imp_->__stack_.push(move(new_s));
+}
+
+void recursive_directory_iterator::__pop(error_code* ec) {
+ _LIBCPP_ASSERT(__imp_, "Popping the end iterator");
+ if (ec)
+ ec->clear();
+ __imp_->__stack_.pop();
+ if (__imp_->__stack_.size() == 0)
+ __imp_.reset();
+ else
+ __advance(ec);
+}
+
+directory_options recursive_directory_iterator::options() const {
+ return __imp_->__options_;
+}
+
+int recursive_directory_iterator::depth() const {
+ return __imp_->__stack_.size() - 1;
+}
+
+const directory_entry& recursive_directory_iterator::__dereference() const {
+ return __imp_->__stack_.top().__entry_;
+}
+
+recursive_directory_iterator&
+recursive_directory_iterator::__increment(error_code* ec) {
+ if (ec)
+ ec->clear();
+ if (recursion_pending()) {
+ if (__try_recursion(ec) || (ec && *ec))
+ return *this;
+ }
+ __rec_ = true;
+ __advance(ec);
+ return *this;
+}
+
+void recursive_directory_iterator::__advance(error_code* ec) {
+ ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
+
+ const directory_iterator end_it;
+ auto& stack = __imp_->__stack_;
+ error_code m_ec;
+ while (stack.size() > 0) {
+ if (stack.top().advance(m_ec))
+ return;
+ if (m_ec)
+ break;
+ stack.pop();
+ }
+
+ if (m_ec) {
+ path root = move(stack.top().__root_);
+ __imp_.reset();
+ err.report(m_ec, "at root \"%s\"", root);
+ } else {
+ __imp_.reset();
+ }
+}
+
+bool recursive_directory_iterator::__try_recursion(error_code* ec) {
+ ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
+
+ bool rec_sym = bool(options() & directory_options::follow_directory_symlink);
+
+ auto& curr_it = __imp_->__stack_.top();
+
+ bool skip_rec = false;
+ error_code m_ec;
+ if (!rec_sym) {
+ file_status st(curr_it.__entry_.__get_sym_ft(&m_ec));
+ if (m_ec && status_known(st))
+ m_ec.clear();
+ if (m_ec || is_symlink(st) || !is_directory(st))
+ skip_rec = true;
+ } else {
+ file_status st(curr_it.__entry_.__get_ft(&m_ec));
+ if (m_ec && status_known(st))
+ m_ec.clear();
+ if (m_ec || !is_directory(st))
+ skip_rec = true;
+ }
+
+ if (!skip_rec) {
+ __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
+ if (new_it.good()) {
+ __imp_->__stack_.push(move(new_it));
+ return true;
+ }
+ }
+ if (m_ec) {
+ const bool allow_eacess =
+ bool(__imp_->__options_ & directory_options::skip_permission_denied);
+ if (m_ec.value() == EACCES && allow_eacess) {
+ if (ec)
+ ec->clear();
+ } else {
+ path at_ent = move(curr_it.__entry_.__p_);
+ __imp_.reset();
+ err.report(m_ec, "attempting recursion into \"%s\"", at_ent);
+ }
+ }
+ return false;
+}
+
+_LIBCPP_END_NAMESPACE_FILESYSTEM
--- /dev/null
+//===----------------------------------------------------------------------===////
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===////
+
+#ifndef FILESYSTEM_COMMON_H
+#define FILESYSTEM_COMMON_H
+
+#include "__config"
+#include "filesystem"
+#include "array"
+#include "chrono"
+#include "cstdlib"
+#include "climits"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <sys/time.h> // for ::utimes as used in __last_write_time
+#include <fcntl.h> /* values for fchmodat */
+
+#include "../include/apple_availability.h"
+
+#if !defined(__APPLE__)
+// We can use the presence of UTIME_OMIT to detect platforms that provide
+// utimensat.
+#if defined(UTIME_OMIT)
+#define _LIBCPP_USE_UTIMENSAT
+#endif
+#endif
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
+
+namespace detail {
+namespace {
+
+static string format_string_imp(const char* msg, ...) {
+ // we might need a second shot at this, so pre-emptivly make a copy
+ struct GuardVAList {
+ va_list& target;
+ bool active = true;
+ GuardVAList(va_list& target) : target(target), active(true) {}
+ void clear() {
+ if (active)
+ va_end(target);
+ active = false;
+ }
+ ~GuardVAList() {
+ if (active)
+ va_end(target);
+ }
+ };
+ va_list args;
+ va_start(args, msg);
+ GuardVAList args_guard(args);
+
+ va_list args_cp;
+ va_copy(args_cp, args);
+ GuardVAList args_copy_guard(args_cp);
+
+ array<char, 256> local_buff;
+ size_t size = local_buff.size();
+ auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp);
+
+ args_copy_guard.clear();
+
+ // handle empty expansion
+ if (ret == 0)
+ return string{};
+ if (static_cast<size_t>(ret) < size)
+ return string(local_buff.data());
+
+ // we did not provide a long enough buffer on our first attempt.
+ // add 1 to size to account for null-byte in size cast to prevent overflow
+ size = static_cast<size_t>(ret) + 1;
+ auto buff_ptr = unique_ptr<char[]>(new char[size]);
+ ret = ::vsnprintf(buff_ptr.get(), size, msg, args);
+ return string(buff_ptr.get());
+}
+
+const char* unwrap(string const& s) { return s.c_str(); }
+const char* unwrap(path const& p) { return p.native().c_str(); }
+template <class Arg>
+Arg const& unwrap(Arg const& a) {
+ static_assert(!is_class<Arg>::value, "cannot pass class here");
+ return a;
+}
+
+template <class... Args>
+string format_string(const char* fmt, Args const&... args) {
+ return format_string_imp(fmt, unwrap(args)...);
+}
+
+error_code capture_errno() {
+ _LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
+ return error_code(errno, generic_category());
+}
+
+template <class T>
+T error_value();
+template <>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
+template <>
+bool error_value<bool>() {
+ return false;
+}
+template <>
+uintmax_t error_value<uintmax_t>() {
+ return uintmax_t(-1);
+}
+template <>
+_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
+ return file_time_type::min();
+}
+template <>
+path error_value<path>() {
+ return {};
+}
+
+template <class T>
+struct ErrorHandler {
+ const char* func_name;
+ error_code* ec = nullptr;
+ const path* p1 = nullptr;
+ const path* p2 = nullptr;
+
+ ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
+ const path* p2 = nullptr)
+ : func_name(fname), ec(ec), p1(p1), p2(p2) {
+ if (ec)
+ ec->clear();
+ }
+
+ T report(const error_code& m_ec) const {
+ if (ec) {
+ *ec = m_ec;
+ return error_value<T>();
+ }
+ string what = string("in ") + func_name;
+ switch (bool(p1) + bool(p2)) {
+ case 0:
+ __throw_filesystem_error(what, m_ec);
+ case 1:
+ __throw_filesystem_error(what, *p1, m_ec);
+ case 2:
+ __throw_filesystem_error(what, *p1, *p2, m_ec);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ template <class... Args>
+ T report(const error_code& m_ec, const char* msg, Args const&... args) const {
+ if (ec) {
+ *ec = m_ec;
+ return error_value<T>();
+ }
+ string what =
+ string("in ") + func_name + ": " + format_string(msg, args...);
+ switch (bool(p1) + bool(p2)) {
+ case 0:
+ __throw_filesystem_error(what, m_ec);
+ case 1:
+ __throw_filesystem_error(what, *p1, m_ec);
+ case 2:
+ __throw_filesystem_error(what, *p1, *p2, m_ec);
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ T report(errc const& err) const { return report(make_error_code(err)); }
+
+ template <class... Args>
+ T report(errc const& err, const char* msg, Args const&... args) const {
+ return report(make_error_code(err), msg, args...);
+ }
+
+private:
+ ErrorHandler(ErrorHandler const&) = delete;
+ ErrorHandler& operator=(ErrorHandler const&) = delete;
+};
+
+using chrono::duration;
+using chrono::duration_cast;
+
+using TimeSpec = struct ::timespec;
+using StatT = struct ::stat;
+
+template <class FileTimeT, class TimeT,
+ bool IsFloat = is_floating_point<typename FileTimeT::rep>::value>
+struct time_util_base {
+ using rep = typename FileTimeT::rep;
+ using fs_duration = typename FileTimeT::duration;
+ using fs_seconds = duration<rep>;
+ using fs_nanoseconds = duration<rep, nano>;
+ using fs_microseconds = duration<rep, micro>;
+
+ static constexpr rep max_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
+
+ static constexpr rep max_nsec =
+ duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
+ fs_seconds(max_seconds))
+ .count();
+
+ static constexpr rep min_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
+
+ static constexpr rep min_nsec_timespec =
+ duration_cast<fs_nanoseconds>(
+ (FileTimeT::duration::min() - fs_seconds(min_seconds)) +
+ fs_seconds(1))
+ .count();
+
+private:
+#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
+ static constexpr fs_duration get_min_nsecs() {
+ return duration_cast<fs_duration>(
+ fs_nanoseconds(min_nsec_timespec) -
+ duration_cast<fs_nanoseconds>(fs_seconds(1)));
+ }
+ // Static assert that these values properly round trip.
+ static_assert(fs_seconds(min_seconds) + get_min_nsecs() ==
+ FileTimeT::duration::min(),
+ "value doesn't roundtrip");
+
+ static constexpr bool check_range() {
+ // This kinda sucks, but it's what happens when we don't have __int128_t.
+ if (sizeof(TimeT) == sizeof(rep)) {
+ typedef duration<long long, ratio<3600 * 24 * 365> > Years;
+ return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) &&
+ duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250);
+ }
+ return max_seconds >= numeric_limits<TimeT>::max() &&
+ min_seconds <= numeric_limits<TimeT>::min();
+ }
+ static_assert(check_range(), "the representable range is unacceptable small");
+#endif
+};
+
+template <class FileTimeT, class TimeT>
+struct time_util_base<FileTimeT, TimeT, true> {
+ using rep = typename FileTimeT::rep;
+ using fs_duration = typename FileTimeT::duration;
+ using fs_seconds = duration<rep>;
+ using fs_nanoseconds = duration<rep, nano>;
+ using fs_microseconds = duration<rep, micro>;
+
+ static const rep max_seconds;
+ static const rep max_nsec;
+ static const rep min_seconds;
+ static const rep min_nsec_timespec;
+};
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep
+ time_util_base<FileTimeT, TimeT, true>::max_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
+ duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
+ fs_seconds(max_seconds))
+ .count();
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep
+ time_util_base<FileTimeT, TimeT, true>::min_seconds =
+ duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
+
+template <class FileTimeT, class TimeT>
+const typename FileTimeT::rep
+ time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
+ duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
+ fs_seconds(min_seconds)) +
+ fs_seconds(1))
+ .count();
+
+template <class FileTimeT, class TimeT, class TimeSpecT>
+struct time_util : time_util_base<FileTimeT, TimeT> {
+ using Base = time_util_base<FileTimeT, TimeT>;
+ using Base::max_nsec;
+ using Base::max_seconds;
+ using Base::min_nsec_timespec;
+ using Base::min_seconds;
+
+ using typename Base::fs_duration;
+ using typename Base::fs_microseconds;
+ using typename Base::fs_nanoseconds;
+ using typename Base::fs_seconds;
+
+public:
+ template <class CType, class ChronoType>
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
+ ChronoType time) {
+ using Lim = numeric_limits<CType>;
+ if (time > Lim::max() || time < Lim::min())
+ return false;
+ *out = static_cast<CType>(time);
+ return true;
+ }
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
+ if (tm.tv_sec >= 0) {
+ return tm.tv_sec < max_seconds ||
+ (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
+ } else if (tm.tv_sec == (min_seconds - 1)) {
+ return tm.tv_nsec >= min_nsec_timespec;
+ } else {
+ return tm.tv_sec >= min_seconds;
+ }
+ }
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
+ auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
+ auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
+ if (nsecs.count() < 0) {
+ secs = secs + fs_seconds(1);
+ nsecs = nsecs + fs_seconds(1);
+ }
+ using TLim = numeric_limits<TimeT>;
+ if (secs.count() >= 0)
+ return secs.count() <= TLim::max();
+ return secs.count() >= TLim::min();
+ }
+
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
+ convert_from_timespec(TimeSpecT tm) {
+ if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
+ return FileTimeT(fs_seconds(tm.tv_sec) +
+ duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
+ } else { // tm.tv_sec < 0
+ auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
+ fs_nanoseconds(tm.tv_nsec));
+ auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
+ return FileTimeT(Dur);
+ }
+ }
+
+ template <class SubSecT>
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
+ set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
+ auto dur = tp.time_since_epoch();
+ auto sec_dur = duration_cast<fs_seconds>(dur);
+ auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
+ // The tv_nsec and tv_usec fields must not be negative so adjust accordingly
+ if (subsec_dur.count() < 0) {
+ if (sec_dur.count() > min_seconds) {
+ sec_dur = sec_dur - fs_seconds(1);
+ subsec_dur = subsec_dur + fs_seconds(1);
+ } else {
+ subsec_dur = fs_nanoseconds::zero();
+ }
+ }
+ return checked_set(sec_out, sec_dur.count()) &&
+ checked_set(subsec_out, subsec_dur.count());
+ }
+ static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
+ FileTimeT tp) {
+ if (!is_representable(tp))
+ return false;
+ return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
+ }
+};
+
+using fs_time = time_util<file_time_type, time_t, TimeSpec>;
+
+#if defined(__APPLE__)
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+#else
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
+#endif
+
+// allow the utimes implementation to compile even it we're not going
+// to use it.
+
+bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
+ error_code& ec) {
+ using namespace chrono;
+ auto Convert = [](long nsec) {
+ using int_type = decltype(std::declval< ::timeval>().tv_usec);
+ auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count();
+ return static_cast<int_type>(dur);
+ };
+ struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
+ {TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
+ if (::utimes(p.c_str(), ConvertedTS) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ return false;
+}
+
+#if defined(_LIBCPP_USE_UTIMENSAT)
+bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS,
+ error_code& ec) {
+ if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ return false;
+}
+#endif
+
+bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS,
+ error_code& ec) {
+#if !defined(_LIBCPP_USE_UTIMENSAT)
+ return posix_utimes(p, TS, ec);
+#else
+ return posix_utimensat(p, TS, ec);
+#endif
+}
+
+} // namespace
+} // end namespace detail
+
+_LIBCPP_END_NAMESPACE_FILESYSTEM
+
+#endif // FILESYSTEM_COMMON_H
--- /dev/null
+/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __muloti4, and is stolen from the compiler_rt library.
+ *
+ * FIXME: we steal and re-compile it into filesystem, which uses __int128_t,
+ * and requires this builtin when sanitized. See llvm.org/PR30643
+ *
+ * ===----------------------------------------------------------------------===
+ */
+#include "__config"
+#include "climits"
+
+#if !defined(_LIBCPP_HAS_NO_INT128)
+
+extern "C" __attribute__((no_sanitize("undefined")))
+__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) {
+ const int N = (int)(sizeof(__int128_t) * CHAR_BIT);
+ const __int128_t MIN = (__int128_t)1 << (N - 1);
+ const __int128_t MAX = ~MIN;
+ *overflow = 0;
+ __int128_t result = a * b;
+ if (a == MIN) {
+ if (b != 0 && b != 1)
+ *overflow = 1;
+ return result;
+ }
+ if (b == MIN) {
+ if (a != 0 && a != 1)
+ *overflow = 1;
+ return result;
+ }
+ __int128_t sa = a >> (N - 1);
+ __int128_t abs_a = (a ^ sa) - sa;
+ __int128_t sb = b >> (N - 1);
+ __int128_t abs_b = (b ^ sb) - sb;
+ if (abs_a < 2 || abs_b < 2)
+ return result;
+ if (sa == sb) {
+ if (abs_a > MAX / abs_b)
+ *overflow = 1;
+ } else {
+ if (abs_a > MIN / -abs_b)
+ *overflow = 1;
+ }
+ return result;
+}
+
+#endif
--- /dev/null
+//===--------------------- filesystem/ops.cpp -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "filesystem"
+#include "array"
+#include "iterator"
+#include "fstream"
+#include "random" /* for unique_path */
+#include "string_view"
+#include "type_traits"
+#include "vector"
+#include "cstdlib"
+#include "climits"
+
+#include "filesystem_common.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <time.h>
+#include <fcntl.h> /* values for fchmodat */
+
+#if defined(__linux__)
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
+#include <sys/sendfile.h>
+#define _LIBCPP_USE_SENDFILE
+#endif
+#elif defined(__APPLE__) || __has_include(<copyfile.h>)
+#include <copyfile.h>
+#define _LIBCPP_USE_COPYFILE
+#endif
+
+#if !defined(__APPLE__)
+#define _LIBCPP_USE_CLOCK_GETTIME
+#endif
+
+#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
+#include <sys/time.h> // for gettimeofday and timeval
+#endif // !defined(CLOCK_REALTIME)
+
+#if defined(_LIBCPP_COMPILER_GCC)
+#if _GNUC_VER < 500
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#endif
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
+
+namespace {
+namespace parser {
+
+using string_view_t = path::__string_view;
+using string_view_pair = pair<string_view_t, string_view_t>;
+using PosPtr = path::value_type const*;
+
+struct PathParser {
+ enum ParserState : unsigned char {
+ // Zero is a special sentinel value used by default constructed iterators.
+ PS_BeforeBegin = path::iterator::_BeforeBegin,
+ PS_InRootName = path::iterator::_InRootName,
+ PS_InRootDir = path::iterator::_InRootDir,
+ PS_InFilenames = path::iterator::_InFilenames,
+ PS_InTrailingSep = path::iterator::_InTrailingSep,
+ PS_AtEnd = path::iterator::_AtEnd
+ };
+
+ const string_view_t Path;
+ string_view_t RawEntry;
+ ParserState State;
+
+private:
+ PathParser(string_view_t P, ParserState State) noexcept : Path(P),
+ State(State) {}
+
+public:
+ PathParser(string_view_t P, string_view_t E, unsigned char S)
+ : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) {
+ // S cannot be '0' or PS_BeforeBegin.
+ }
+
+ static PathParser CreateBegin(string_view_t P) noexcept {
+ PathParser PP(P, PS_BeforeBegin);
+ PP.increment();
+ return PP;
+ }
+
+ static PathParser CreateEnd(string_view_t P) noexcept {
+ PathParser PP(P, PS_AtEnd);
+ return PP;
+ }
+
+ PosPtr peek() const noexcept {
+ auto TkEnd = getNextTokenStartPos();
+ auto End = getAfterBack();
+ return TkEnd == End ? nullptr : TkEnd;
+ }
+
+ void increment() noexcept {
+ const PosPtr End = getAfterBack();
+ const PosPtr Start = getNextTokenStartPos();
+ if (Start == End)
+ return makeState(PS_AtEnd);
+
+ switch (State) {
+ case PS_BeforeBegin: {
+ PosPtr TkEnd = consumeSeparator(Start, End);
+ if (TkEnd)
+ return makeState(PS_InRootDir, Start, TkEnd);
+ else
+ return makeState(PS_InFilenames, Start, consumeName(Start, End));
+ }
+ case PS_InRootDir:
+ return makeState(PS_InFilenames, Start, consumeName(Start, End));
+
+ case PS_InFilenames: {
+ PosPtr SepEnd = consumeSeparator(Start, End);
+ if (SepEnd != End) {
+ PosPtr TkEnd = consumeName(SepEnd, End);
+ if (TkEnd)
+ return makeState(PS_InFilenames, SepEnd, TkEnd);
+ }
+ return makeState(PS_InTrailingSep, Start, SepEnd);
+ }
+
+ case PS_InTrailingSep:
+ return makeState(PS_AtEnd);
+
+ case PS_InRootName:
+ case PS_AtEnd:
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+
+ void decrement() noexcept {
+ const PosPtr REnd = getBeforeFront();
+ const PosPtr RStart = getCurrentTokenStartPos() - 1;
+ if (RStart == REnd) // we're decrementing the begin
+ return makeState(PS_BeforeBegin);
+
+ switch (State) {
+ case PS_AtEnd: {
+ // Try to consume a trailing separator or root directory first.
+ if (PosPtr SepEnd = consumeSeparator(RStart, REnd)) {
+ if (SepEnd == REnd)
+ return makeState(PS_InRootDir, Path.data(), RStart + 1);
+ return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1);
+ } else {
+ PosPtr TkStart = consumeName(RStart, REnd);
+ return makeState(PS_InFilenames, TkStart + 1, RStart + 1);
+ }
+ }
+ case PS_InTrailingSep:
+ return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1,
+ RStart + 1);
+ case PS_InFilenames: {
+ PosPtr SepEnd = consumeSeparator(RStart, REnd);
+ if (SepEnd == REnd)
+ return makeState(PS_InRootDir, Path.data(), RStart + 1);
+ PosPtr TkEnd = consumeName(SepEnd, REnd);
+ return makeState(PS_InFilenames, TkEnd + 1, SepEnd + 1);
+ }
+ case PS_InRootDir:
+ // return makeState(PS_InRootName, Path.data(), RStart + 1);
+ case PS_InRootName:
+ case PS_BeforeBegin:
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+
+ /// \brief Return a view with the "preferred representation" of the current
+ /// element. For example trailing separators are represented as a '.'
+ string_view_t operator*() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ case PS_AtEnd:
+ return "";
+ case PS_InRootDir:
+ return "/";
+ case PS_InTrailingSep:
+ return "";
+ case PS_InRootName:
+ case PS_InFilenames:
+ return RawEntry;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ explicit operator bool() const noexcept {
+ return State != PS_BeforeBegin && State != PS_AtEnd;
+ }
+
+ PathParser& operator++() noexcept {
+ increment();
+ return *this;
+ }
+
+ PathParser& operator--() noexcept {
+ decrement();
+ return *this;
+ }
+
+ bool inRootPath() const noexcept {
+ return State == PS_InRootDir || State == PS_InRootName;
+ }
+
+private:
+ void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept {
+ State = NewState;
+ RawEntry = string_view_t(Start, End - Start);
+ }
+ void makeState(ParserState NewState) noexcept {
+ State = NewState;
+ RawEntry = {};
+ }
+
+ PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); }
+
+ PosPtr getBeforeFront() const noexcept { return Path.data() - 1; }
+
+ /// \brief Return a pointer to the first character after the currently
+ /// lexed element.
+ PosPtr getNextTokenStartPos() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ return Path.data();
+ case PS_InRootName:
+ case PS_InRootDir:
+ case PS_InFilenames:
+ return &RawEntry.back() + 1;
+ case PS_InTrailingSep:
+ case PS_AtEnd:
+ return getAfterBack();
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ /// \brief Return a pointer to the first character in the currently lexed
+ /// element.
+ PosPtr getCurrentTokenStartPos() const noexcept {
+ switch (State) {
+ case PS_BeforeBegin:
+ case PS_InRootName:
+ return &Path.front();
+ case PS_InRootDir:
+ case PS_InFilenames:
+ case PS_InTrailingSep:
+ return &RawEntry.front();
+ case PS_AtEnd:
+ return &Path.back() + 1;
+ }
+ _LIBCPP_UNREACHABLE();
+ }
+
+ PosPtr consumeSeparator(PosPtr P, PosPtr End) const noexcept {
+ if (P == End || *P != '/')
+ return nullptr;
+ const int Inc = P < End ? 1 : -1;
+ P += Inc;
+ while (P != End && *P == '/')
+ P += Inc;
+ return P;
+ }
+
+ PosPtr consumeName(PosPtr P, PosPtr End) const noexcept {
+ if (P == End || *P == '/')
+ return nullptr;
+ const int Inc = P < End ? 1 : -1;
+ P += Inc;
+ while (P != End && *P != '/')
+ P += Inc;
+ return P;
+ }
+};
+
+string_view_pair separate_filename(string_view_t const& s) {
+ if (s == "." || s == ".." || s.empty())
+ return string_view_pair{s, ""};
+ auto pos = s.find_last_of('.');
+ if (pos == string_view_t::npos || pos == 0)
+ return string_view_pair{s, string_view_t{}};
+ return string_view_pair{s.substr(0, pos), s.substr(pos)};
+}
+
+string_view_t createView(PosPtr S, PosPtr E) noexcept {
+ return {S, static_cast<size_t>(E - S) + 1};
+}
+
+} // namespace parser
+} // namespace
+
+// POSIX HELPERS
+
+namespace detail {
+namespace {
+
+using value_type = path::value_type;
+using string_type = path::string_type;
+
+struct FileDescriptor {
+ const path& name;
+ int fd = -1;
+ StatT m_stat;
+ file_status m_status;
+
+ template <class... Args>
+ static FileDescriptor create(const path* p, error_code& ec, Args... args) {
+ ec.clear();
+ int fd;
+ if ((fd = ::open(p->c_str(), args...)) == -1) {
+ ec = capture_errno();
+ return FileDescriptor{p};
+ }
+ return FileDescriptor(p, fd);
+ }
+
+ template <class... Args>
+ static FileDescriptor create_with_status(const path* p, error_code& ec,
+ Args... args) {
+ FileDescriptor fd = create(p, ec, args...);
+ if (!ec)
+ fd.refresh_status(ec);
+
+ return fd;
+ }
+
+ file_status get_status() const { return m_status; }
+ StatT const& get_stat() const { return m_stat; }
+
+ bool status_known() const { return _VSTD_FS::status_known(m_status); }
+
+ file_status refresh_status(error_code& ec);
+
+ void close() noexcept {
+ if (fd != -1)
+ ::close(fd);
+ fd = -1;
+ }
+
+ FileDescriptor(FileDescriptor&& other)
+ : name(other.name), fd(other.fd), m_stat(other.m_stat),
+ m_status(other.m_status) {
+ other.fd = -1;
+ other.m_status = file_status{};
+ }
+
+ ~FileDescriptor() { close(); }
+
+ FileDescriptor() = default;
+ FileDescriptor(FileDescriptor const&) = delete;
+ FileDescriptor& operator=(FileDescriptor const&) = delete;
+
+private:
+ explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {}
+};
+
+perms posix_get_perms(const StatT& st) noexcept {
+ return static_cast<perms>(st.st_mode) & perms::mask;
+}
+
+::mode_t posix_convert_perms(perms prms) {
+ return static_cast< ::mode_t>(prms & perms::mask);
+}
+
+file_status create_file_status(error_code& m_ec, path const& p,
+ const StatT& path_stat, error_code* ec) {
+ if (ec)
+ *ec = m_ec;
+ if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) {
+ return file_status(file_type::not_found);
+ } else if (m_ec) {
+ ErrorHandler<void> err("posix_stat", ec, &p);
+ err.report(m_ec, "failed to determine attributes for the specified path");
+ return file_status(file_type::none);
+ }
+ // else
+
+ file_status fs_tmp;
+ auto const mode = path_stat.st_mode;
+ if (S_ISLNK(mode))
+ fs_tmp.type(file_type::symlink);
+ else if (S_ISREG(mode))
+ fs_tmp.type(file_type::regular);
+ else if (S_ISDIR(mode))
+ fs_tmp.type(file_type::directory);
+ else if (S_ISBLK(mode))
+ fs_tmp.type(file_type::block);
+ else if (S_ISCHR(mode))
+ fs_tmp.type(file_type::character);
+ else if (S_ISFIFO(mode))
+ fs_tmp.type(file_type::fifo);
+ else if (S_ISSOCK(mode))
+ fs_tmp.type(file_type::socket);
+ else
+ fs_tmp.type(file_type::unknown);
+
+ fs_tmp.permissions(detail::posix_get_perms(path_stat));
+ return fs_tmp;
+}
+
+file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) {
+ error_code m_ec;
+ if (::stat(p.c_str(), &path_stat) == -1)
+ m_ec = detail::capture_errno();
+ return create_file_status(m_ec, p, path_stat, ec);
+}
+
+file_status posix_stat(path const& p, error_code* ec) {
+ StatT path_stat;
+ return posix_stat(p, path_stat, ec);
+}
+
+file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) {
+ error_code m_ec;
+ if (::lstat(p.c_str(), &path_stat) == -1)
+ m_ec = detail::capture_errno();
+ return create_file_status(m_ec, p, path_stat, ec);
+}
+
+file_status posix_lstat(path const& p, error_code* ec) {
+ StatT path_stat;
+ return posix_lstat(p, path_stat, ec);
+}
+
+bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) {
+ if (::ftruncate(fd.fd, to_size) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ ec.clear();
+ return false;
+}
+
+bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) {
+ if (::fchmod(fd.fd, st.st_mode) == -1) {
+ ec = capture_errno();
+ return true;
+ }
+ ec.clear();
+ return false;
+}
+
+bool stat_equivalent(const StatT& st1, const StatT& st2) {
+ return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+}
+
+file_status FileDescriptor::refresh_status(error_code& ec) {
+ // FD must be open and good.
+ m_status = file_status{};
+ m_stat = {};
+ error_code m_ec;
+ if (::fstat(fd, &m_stat) == -1)
+ m_ec = capture_errno();
+ m_status = create_file_status(m_ec, name, m_stat, &ec);
+ return m_status;
+}
+} // namespace
+} // end namespace detail
+
+using detail::capture_errno;
+using detail::ErrorHandler;
+using detail::StatT;
+using detail::TimeSpec;
+using parser::createView;
+using parser::PathParser;
+using parser::string_view_t;
+
+const bool _FilesystemClock::is_steady;
+
+_FilesystemClock::time_point _FilesystemClock::now() noexcept {
+ typedef chrono::duration<rep> __secs;
+#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
+ typedef chrono::duration<rep, nano> __nsecs;
+ struct timespec tp;
+ if (0 != clock_gettime(CLOCK_REALTIME, &tp))
+ __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
+ return time_point(__secs(tp.tv_sec) +
+ chrono::duration_cast<duration>(__nsecs(tp.tv_nsec)));
+#else
+ typedef chrono::duration<rep, micro> __microsecs;
+ timeval tv;
+ gettimeofday(&tv, 0);
+ return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec));
+#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
+}
+
+filesystem_error::~filesystem_error() {}
+
+void filesystem_error::__create_what(int __num_paths) {
+ const char* derived_what = system_error::what();
+ __storage_->__what_ = [&]() -> string {
+ const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str();
+ const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str();
+ switch (__num_paths) {
+ default:
+ return detail::format_string("filesystem error: %s", derived_what);
+ case 1:
+ return detail::format_string("filesystem error: %s [%s]", derived_what,
+ p1);
+ case 2:
+ return detail::format_string("filesystem error: %s [%s] [%s]",
+ derived_what, p1, p2);
+ }
+ }();
+}
+
+static path __do_absolute(const path& p, path* cwd, error_code* ec) {
+ if (ec)
+ ec->clear();
+ if (p.is_absolute())
+ return p;
+ *cwd = __current_path(ec);
+ if (ec && *ec)
+ return {};
+ return (*cwd) / p;
+}
+
+path __absolute(const path& p, error_code* ec) {
+ path cwd;
+ return __do_absolute(p, &cwd, ec);
+}
+
+path __canonical(path const& orig_p, error_code* ec) {
+ path cwd;
+ ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
+
+ path p = __do_absolute(orig_p, &cwd, ec);
+ char buff[PATH_MAX + 1];
+ char* ret;
+ if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
+ return err.report(capture_errno());
+ return {ret};
+}
+
+void __copy(const path& from, const path& to, copy_options options,
+ error_code* ec) {
+ ErrorHandler<void> err("copy", ec, &from, &to);
+
+ const bool sym_status = bool(
+ options & (copy_options::create_symlinks | copy_options::skip_symlinks));
+
+ const bool sym_status2 = bool(options & copy_options::copy_symlinks);
+
+ error_code m_ec1;
+ StatT f_st = {};
+ const file_status f = sym_status || sym_status2
+ ? detail::posix_lstat(from, f_st, &m_ec1)
+ : detail::posix_stat(from, f_st, &m_ec1);
+ if (m_ec1)
+ return err.report(m_ec1);
+
+ StatT t_st = {};
+ const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1)
+ : detail::posix_stat(to, t_st, &m_ec1);
+
+ if (not status_known(t))
+ return err.report(m_ec1);
+
+ if (!exists(f) || is_other(f) || is_other(t) ||
+ (is_directory(f) && is_regular_file(t)) ||
+ detail::stat_equivalent(f_st, t_st)) {
+ return err.report(errc::function_not_supported);
+ }
+
+ if (ec)
+ ec->clear();
+
+ if (is_symlink(f)) {
+ if (bool(copy_options::skip_symlinks & options)) {
+ // do nothing
+ } else if (not exists(t)) {
+ __copy_symlink(from, to, ec);
+ } else {
+ return err.report(errc::file_exists);
+ }
+ return;
+ } else if (is_regular_file(f)) {
+ if (bool(copy_options::directories_only & options)) {
+ // do nothing
+ } else if (bool(copy_options::create_symlinks & options)) {
+ __create_symlink(from, to, ec);
+ } else if (bool(copy_options::create_hard_links & options)) {
+ __create_hard_link(from, to, ec);
+ } else if (is_directory(t)) {
+ __copy_file(from, to / from.filename(), options, ec);
+ } else {
+ __copy_file(from, to, options, ec);
+ }
+ return;
+ } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) {
+ return err.report(errc::is_a_directory);
+ } else if (is_directory(f) && (bool(copy_options::recursive & options) ||
+ copy_options::none == options)) {
+
+ if (!exists(t)) {
+ // create directory to with attributes from 'from'.
+ __create_directory(to, from, ec);
+ if (ec && *ec) {
+ return;
+ }
+ }
+ directory_iterator it =
+ ec ? directory_iterator(from, *ec) : directory_iterator(from);
+ if (ec && *ec) {
+ return;
+ }
+ error_code m_ec2;
+ for (; it != directory_iterator(); it.increment(m_ec2)) {
+ if (m_ec2) {
+ return err.report(m_ec2);
+ }
+ __copy(it->path(), to / it->path().filename(),
+ options | copy_options::__in_recursive_copy, ec);
+ if (ec && *ec) {
+ return;
+ }
+ }
+ }
+}
+
+namespace detail {
+namespace {
+
+#ifdef _LIBCPP_USE_SENDFILE
+bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
+ error_code& ec) {
+
+ size_t count = read_fd.get_stat().st_size;
+ do {
+ ssize_t res;
+ if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) {
+ ec = capture_errno();
+ return false;
+ }
+ count -= res;
+ } while (count > 0);
+
+ ec.clear();
+
+ return true;
+}
+#elif defined(_LIBCPP_USE_COPYFILE)
+bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd,
+ error_code& ec) {
+ struct CopyFileState {
+ copyfile_state_t state;
+ CopyFileState() { state = copyfile_state_alloc(); }
+ ~CopyFileState() { copyfile_state_free(state); }
+
+ private:
+ CopyFileState(CopyFileState const&) = delete;
+ CopyFileState& operator=(CopyFileState const&) = delete;
+ };
+
+ CopyFileState cfs;
+ if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) {
+ ec = capture_errno();
+ return false;
+ }
+
+ ec.clear();
+ return true;
+}
+#endif
+
+// Note: This function isn't guarded by ifdef's even though it may be unused
+// in order to assure it still compiles.
+__attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd,
+ FileDescriptor& write_fd,
+ error_code& ec) {
+ ifstream in;
+ in.__open(read_fd.fd, ios::binary);
+ if (!in.is_open()) {
+ // This assumes that __open didn't reset the error code.
+ ec = capture_errno();
+ return false;
+ }
+ ofstream out;
+ out.__open(write_fd.fd, ios::binary);
+ if (!out.is_open()) {
+ ec = capture_errno();
+ return false;
+ }
+
+ if (in.good() && out.good()) {
+ using InIt = istreambuf_iterator<char>;
+ using OutIt = ostreambuf_iterator<char>;
+ InIt bin(in);
+ InIt ein;
+ OutIt bout(out);
+ copy(bin, ein, bout);
+ }
+ if (out.fail() || in.fail()) {
+ ec = make_error_code(errc::io_error);
+ return false;
+ }
+
+ ec.clear();
+ return true;
+}
+
+bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) {
+#if defined(_LIBCPP_USE_SENDFILE)
+ return copy_file_impl_sendfile(from, to, ec);
+#elif defined(_LIBCPP_USE_COPYFILE)
+ return copy_file_impl_copyfile(from, to, ec);
+#else
+ return copy_file_impl_default(from, to, ec);
+#endif
+}
+
+} // namespace
+} // namespace detail
+
+bool __copy_file(const path& from, const path& to, copy_options options,
+ error_code* ec) {
+ using detail::FileDescriptor;
+ ErrorHandler<bool> err("copy_file", ec, &to, &from);
+
+ error_code m_ec;
+ FileDescriptor from_fd =
+ FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK);
+ if (m_ec)
+ return err.report(m_ec);
+
+ auto from_st = from_fd.get_status();
+ StatT const& from_stat = from_fd.get_stat();
+ if (!is_regular_file(from_st)) {
+ if (not m_ec)
+ m_ec = make_error_code(errc::not_supported);
+ return err.report(m_ec);
+ }
+
+ const bool skip_existing = bool(copy_options::skip_existing & options);
+ const bool update_existing = bool(copy_options::update_existing & options);
+ const bool overwrite_existing =
+ bool(copy_options::overwrite_existing & options);
+
+ StatT to_stat_path;
+ file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec);
+ if (!status_known(to_st))
+ return err.report(m_ec);
+
+ const bool to_exists = exists(to_st);
+ if (to_exists && !is_regular_file(to_st))
+ return err.report(errc::not_supported);
+
+ if (to_exists && detail::stat_equivalent(from_stat, to_stat_path))
+ return err.report(errc::file_exists);
+
+ if (to_exists && skip_existing)
+ return false;
+
+ bool ShouldCopy = [&]() {
+ if (to_exists && update_existing) {
+ auto from_time = detail::extract_mtime(from_stat);
+ auto to_time = detail::extract_mtime(to_stat_path);
+ if (from_time.tv_sec < to_time.tv_sec)
+ return false;
+ if (from_time.tv_sec == to_time.tv_sec &&
+ from_time.tv_nsec <= to_time.tv_nsec)
+ return false;
+ return true;
+ }
+ if (!to_exists || overwrite_existing)
+ return true;
+ return err.report(errc::file_exists);
+ }();
+ if (!ShouldCopy)
+ return false;
+
+ // Don't truncate right away. We may not be opening the file we originally
+ // looked at; we'll check this later.
+ int to_open_flags = O_WRONLY;
+ if (!to_exists)
+ to_open_flags |= O_CREAT;
+ FileDescriptor to_fd = FileDescriptor::create_with_status(
+ &to, m_ec, to_open_flags, from_stat.st_mode);
+ if (m_ec)
+ return err.report(m_ec);
+
+ if (to_exists) {
+ // Check that the file we initially stat'ed is equivalent to the one
+ // we opened.
+ // FIXME: report this better.
+ if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat()))
+ return err.report(errc::bad_file_descriptor);
+
+ // Set the permissions and truncate the file we opened.
+ if (detail::posix_fchmod(to_fd, from_stat, m_ec))
+ return err.report(m_ec);
+ if (detail::posix_ftruncate(to_fd, 0, m_ec))
+ return err.report(m_ec);
+ }
+
+ if (!copy_file_impl(from_fd, to_fd, m_ec)) {
+ // FIXME: Remove the dest file if we failed, and it didn't exist previously.
+ return err.report(m_ec);
+ }
+
+ return true;
+}
+
+void __copy_symlink(const path& existing_symlink, const path& new_symlink,
+ error_code* ec) {
+ const path real_path(__read_symlink(existing_symlink, ec));
+ if (ec && *ec) {
+ return;
+ }
+ // NOTE: proposal says you should detect if you should call
+ // create_symlink or create_directory_symlink. I don't think this
+ // is needed with POSIX
+ __create_symlink(real_path, new_symlink, ec);
+}
+
+bool __create_directories(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("create_directories", ec, &p);
+
+ error_code m_ec;
+ auto const st = detail::posix_stat(p, &m_ec);
+ if (!status_known(st))
+ return err.report(m_ec);
+ else if (is_directory(st))
+ return false;
+ else if (exists(st))
+ return err.report(errc::file_exists);
+
+ const path parent = p.parent_path();
+ if (!parent.empty()) {
+ const file_status parent_st = status(parent, m_ec);
+ if (not status_known(parent_st))
+ return err.report(m_ec);
+ if (not exists(parent_st)) {
+ __create_directories(parent, ec);
+ if (ec && *ec) {
+ return false;
+ }
+ }
+ }
+ return __create_directory(p, ec);
+}
+
+bool __create_directory(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("create_directory", ec, &p);
+
+ if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0)
+ return true;
+ if (errno != EEXIST)
+ err.report(capture_errno());
+ return false;
+}
+
+bool __create_directory(path const& p, path const& attributes, error_code* ec) {
+ ErrorHandler<bool> err("create_directory", ec, &p, &attributes);
+
+ StatT attr_stat;
+ error_code mec;
+ auto st = detail::posix_stat(attributes, attr_stat, &mec);
+ if (!status_known(st))
+ return err.report(mec);
+ if (!is_directory(st))
+ return err.report(errc::not_a_directory,
+ "the specified attribute path is invalid");
+
+ if (::mkdir(p.c_str(), attr_stat.st_mode) == 0)
+ return true;
+ if (errno != EEXIST)
+ err.report(capture_errno());
+ return false;
+}
+
+void __create_directory_symlink(path const& from, path const& to,
+ error_code* ec) {
+ ErrorHandler<void> err("create_directory_symlink", ec, &from, &to);
+ if (::symlink(from.c_str(), to.c_str()) != 0)
+ return err.report(capture_errno());
+}
+
+void __create_hard_link(const path& from, const path& to, error_code* ec) {
+ ErrorHandler<void> err("create_hard_link", ec, &from, &to);
+ if (::link(from.c_str(), to.c_str()) == -1)
+ return err.report(capture_errno());
+}
+
+void __create_symlink(path const& from, path const& to, error_code* ec) {
+ ErrorHandler<void> err("create_symlink", ec, &from, &to);
+ if (::symlink(from.c_str(), to.c_str()) == -1)
+ return err.report(capture_errno());
+}
+
+path __current_path(error_code* ec) {
+ ErrorHandler<path> err("current_path", ec);
+
+ auto size = ::pathconf(".", _PC_PATH_MAX);
+ _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size");
+
+ auto buff = unique_ptr<char[]>(new char[size + 1]);
+ char* ret;
+ if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr)
+ return err.report(capture_errno(), "call to getcwd failed");
+
+ return {buff.get()};
+}
+
+void __current_path(const path& p, error_code* ec) {
+ ErrorHandler<void> err("current_path", ec, &p);
+ if (::chdir(p.c_str()) == -1)
+ err.report(capture_errno());
+}
+
+bool __equivalent(const path& p1, const path& p2, error_code* ec) {
+ ErrorHandler<bool> err("equivalent", ec, &p1, &p2);
+
+ error_code ec1, ec2;
+ StatT st1 = {}, st2 = {};
+ auto s1 = detail::posix_stat(p1.native(), st1, &ec1);
+ if (!exists(s1))
+ return err.report(errc::not_supported);
+ auto s2 = detail::posix_stat(p2.native(), st2, &ec2);
+ if (!exists(s2))
+ return err.report(errc::not_supported);
+
+ return detail::stat_equivalent(st1, st2);
+}
+
+uintmax_t __file_size(const path& p, error_code* ec) {
+ ErrorHandler<uintmax_t> err("file_size", ec, &p);
+
+ error_code m_ec;
+ StatT st;
+ file_status fst = detail::posix_stat(p, st, &m_ec);
+ if (!exists(fst) || !is_regular_file(fst)) {
+ errc error_kind =
+ is_directory(fst) ? errc::is_a_directory : errc::not_supported;
+ if (!m_ec)
+ m_ec = make_error_code(error_kind);
+ return err.report(m_ec);
+ }
+ // is_regular_file(p) == true
+ return static_cast<uintmax_t>(st.st_size);
+}
+
+uintmax_t __hard_link_count(const path& p, error_code* ec) {
+ ErrorHandler<uintmax_t> err("hard_link_count", ec, &p);
+
+ error_code m_ec;
+ StatT st;
+ detail::posix_stat(p, st, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ return static_cast<uintmax_t>(st.st_nlink);
+}
+
+bool __fs_is_empty(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("is_empty", ec, &p);
+
+ error_code m_ec;
+ StatT pst;
+ auto st = detail::posix_stat(p, pst, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ else if (!is_directory(st) && !is_regular_file(st))
+ return err.report(errc::not_supported);
+ else if (is_directory(st)) {
+ auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p);
+ if (ec && *ec)
+ return false;
+ return it == directory_iterator{};
+ } else if (is_regular_file(st))
+ return static_cast<uintmax_t>(pst.st_size) == 0;
+
+ _LIBCPP_UNREACHABLE();
+}
+
+static file_time_type __extract_last_write_time(const path& p, const StatT& st,
+ error_code* ec) {
+ using detail::fs_time;
+ ErrorHandler<file_time_type> err("last_write_time", ec, &p);
+
+ auto ts = detail::extract_mtime(st);
+ if (!fs_time::is_representable(ts))
+ return err.report(errc::value_too_large);
+
+ return fs_time::convert_from_timespec(ts);
+}
+
+file_time_type __last_write_time(const path& p, error_code* ec) {
+ using namespace chrono;
+ ErrorHandler<file_time_type> err("last_write_time", ec, &p);
+
+ error_code m_ec;
+ StatT st;
+ detail::posix_stat(p, st, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ return __extract_last_write_time(p, st, ec);
+}
+
+void __last_write_time(const path& p, file_time_type new_time, error_code* ec) {
+ using detail::fs_time;
+ ErrorHandler<void> err("last_write_time", ec, &p);
+
+ error_code m_ec;
+ array<TimeSpec, 2> tbuf;
+#if !defined(_LIBCPP_USE_UTIMENSAT)
+ // This implementation has a race condition between determining the
+ // last access time and attempting to set it to the same value using
+ // ::utimes
+ StatT st;
+ file_status fst = detail::posix_stat(p, st, &m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+ tbuf[0] = detail::extract_atime(st);
+#else
+ tbuf[0].tv_sec = 0;
+ tbuf[0].tv_nsec = UTIME_OMIT;
+#endif
+ if (!fs_time::convert_to_timespec(tbuf[1], new_time))
+ return err.report(errc::value_too_large);
+
+ detail::set_file_times(p, tbuf, m_ec);
+ if (m_ec)
+ return err.report(m_ec);
+}
+
+void __permissions(const path& p, perms prms, perm_options opts,
+ error_code* ec) {
+ ErrorHandler<void> err("permissions", ec, &p);
+
+ auto has_opt = [&](perm_options o) { return bool(o & opts); };
+ const bool resolve_symlinks = !has_opt(perm_options::nofollow);
+ const bool add_perms = has_opt(perm_options::add);
+ const bool remove_perms = has_opt(perm_options::remove);
+ _LIBCPP_ASSERT(
+ (add_perms + remove_perms + has_opt(perm_options::replace)) == 1,
+ "One and only one of the perm_options constants replace, add, or remove "
+ "is present in opts");
+
+ bool set_sym_perms = false;
+ prms &= perms::mask;
+ if (!resolve_symlinks || (add_perms || remove_perms)) {
+ error_code m_ec;
+ file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec)
+ : detail::posix_lstat(p, &m_ec);
+ set_sym_perms = is_symlink(st);
+ if (m_ec)
+ return err.report(m_ec);
+ _LIBCPP_ASSERT(st.permissions() != perms::unknown,
+ "Permissions unexpectedly unknown");
+ if (add_perms)
+ prms |= st.permissions();
+ else if (remove_perms)
+ prms = st.permissions() & ~prms;
+ }
+ const auto real_perms = detail::posix_convert_perms(prms);
+
+#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD)
+ const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0;
+ if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) {
+ return err.report(capture_errno());
+ }
+#else
+ if (set_sym_perms)
+ return err.report(errc::operation_not_supported);
+ if (::chmod(p.c_str(), real_perms) == -1) {
+ return err.report(capture_errno());
+ }
+#endif
+}
+
+path __read_symlink(const path& p, error_code* ec) {
+ ErrorHandler<path> err("read_symlink", ec, &p);
+
+ char buff[PATH_MAX + 1];
+ error_code m_ec;
+ ::ssize_t ret;
+ if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) {
+ return err.report(capture_errno());
+ }
+ _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO");
+ _LIBCPP_ASSERT(ret > 0, "TODO");
+ buff[ret] = 0;
+ return {buff};
+}
+
+bool __remove(const path& p, error_code* ec) {
+ ErrorHandler<bool> err("remove", ec, &p);
+ if (::remove(p.c_str()) == -1) {
+ if (errno != ENOENT)
+ err.report(capture_errno());
+ return false;
+ }
+ return true;
+}
+
+namespace {
+
+uintmax_t remove_all_impl(path const& p, error_code& ec) {
+ const auto npos = static_cast<uintmax_t>(-1);
+ const file_status st = __symlink_status(p, &ec);
+ if (ec)
+ return npos;
+ uintmax_t count = 1;
+ if (is_directory(st)) {
+ for (directory_iterator it(p, ec); !ec && it != directory_iterator();
+ it.increment(ec)) {
+ auto other_count = remove_all_impl(it->path(), ec);
+ if (ec)
+ return npos;
+ count += other_count;
+ }
+ if (ec)
+ return npos;
+ }
+ if (!__remove(p, &ec))
+ return npos;
+ return count;
+}
+
+} // end namespace
+
+uintmax_t __remove_all(const path& p, error_code* ec) {
+ ErrorHandler<uintmax_t> err("remove_all", ec, &p);
+
+ error_code mec;
+ auto count = remove_all_impl(p, mec);
+ if (mec) {
+ if (mec == errc::no_such_file_or_directory)
+ return 0;
+ return err.report(mec);
+ }
+ return count;
+}
+
+void __rename(const path& from, const path& to, error_code* ec) {
+ ErrorHandler<void> err("rename", ec, &from, &to);
+ if (::rename(from.c_str(), to.c_str()) == -1)
+ err.report(capture_errno());
+}
+
+void __resize_file(const path& p, uintmax_t size, error_code* ec) {
+ ErrorHandler<void> err("resize_file", ec, &p);
+ if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1)
+ return err.report(capture_errno());
+}
+
+space_info __space(const path& p, error_code* ec) {
+ ErrorHandler<void> err("space", ec, &p);
+ space_info si;
+ struct statvfs m_svfs = {};
+ if (::statvfs(p.c_str(), &m_svfs) == -1) {
+ err.report(capture_errno());
+ si.capacity = si.free = si.available = static_cast<uintmax_t>(-1);
+ return si;
+ }
+ // Multiply with overflow checking.
+ auto do_mult = [&](uintmax_t& out, uintmax_t other) {
+ out = other * m_svfs.f_frsize;
+ if (other == 0 || out / other != m_svfs.f_frsize)
+ out = static_cast<uintmax_t>(-1);
+ };
+ do_mult(si.capacity, m_svfs.f_blocks);
+ do_mult(si.free, m_svfs.f_bfree);
+ do_mult(si.available, m_svfs.f_bavail);
+ return si;
+}
+
+file_status __status(const path& p, error_code* ec) {
+ return detail::posix_stat(p, ec);
+}
+
+file_status __symlink_status(const path& p, error_code* ec) {
+ return detail::posix_lstat(p, ec);
+}
+
+path __temp_directory_path(error_code* ec) {
+ ErrorHandler<path> err("temp_directory_path", ec);
+
+ const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
+ const char* ret = nullptr;
+
+ for (auto& ep : env_paths)
+ if ((ret = getenv(ep)))
+ break;
+ if (ret == nullptr)
+ ret = "/tmp";
+
+ path p(ret);
+ error_code m_ec;
+ file_status st = detail::posix_stat(p, &m_ec);
+ if (!status_known(st))
+ return err.report(m_ec, "cannot access path \"%s\"", p);
+
+ if (!exists(st) || !is_directory(st))
+ return err.report(errc::not_a_directory, "path \"%s\" is not a directory",
+ p);
+
+ return p;
+}
+
+path __weakly_canonical(const path& p, error_code* ec) {
+ ErrorHandler<path> err("weakly_canonical", ec, &p);
+
+ if (p.empty())
+ return __canonical("", ec);
+
+ path result;
+ path tmp;
+ tmp.__reserve(p.native().size());
+ auto PP = PathParser::CreateEnd(p.native());
+ --PP;
+ vector<string_view_t> DNEParts;
+
+ while (PP.State != PathParser::PS_BeforeBegin) {
+ tmp.assign(createView(p.native().data(), &PP.RawEntry.back()));
+ error_code m_ec;
+ file_status st = __status(tmp, &m_ec);
+ if (!status_known(st)) {
+ return err.report(m_ec);
+ } else if (exists(st)) {
+ result = __canonical(tmp, ec);
+ break;
+ }
+ DNEParts.push_back(*PP);
+ --PP;
+ }
+ if (PP.State == PathParser::PS_BeforeBegin)
+ result = __canonical("", ec);
+ if (ec)
+ ec->clear();
+ if (DNEParts.empty())
+ return result;
+ for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It)
+ result /= *It;
+ return result.lexically_normal();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// path definitions
+///////////////////////////////////////////////////////////////////////////////
+
+constexpr path::value_type path::preferred_separator;
+
+path& path::replace_extension(path const& replacement) {
+ path p = extension();
+ if (not p.empty()) {
+ __pn_.erase(__pn_.size() - p.native().size());
+ }
+ if (!replacement.empty()) {
+ if (replacement.native()[0] != '.') {
+ __pn_ += ".";
+ }
+ __pn_.append(replacement.__pn_);
+ }
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// path.decompose
+
+string_view_t path::__root_name() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName)
+ return *PP;
+ return {};
+}
+
+string_view_t path::__root_directory() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName)
+ ++PP;
+ if (PP.State == PathParser::PS_InRootDir)
+ return *PP;
+ return {};
+}
+
+string_view_t path::__root_path_raw() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (PP.State == PathParser::PS_InRootName) {
+ auto NextCh = PP.peek();
+ if (NextCh && *NextCh == '/') {
+ ++PP;
+ return createView(__pn_.data(), &PP.RawEntry.back());
+ }
+ return PP.RawEntry;
+ }
+ if (PP.State == PathParser::PS_InRootDir)
+ return *PP;
+ return {};
+}
+
+static bool ConsumeRootDir(PathParser* PP) {
+ while (PP->State <= PathParser::PS_InRootDir)
+ ++(*PP);
+ return PP->State == PathParser::PS_AtEnd;
+}
+
+string_view_t path::__relative_path() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (ConsumeRootDir(&PP))
+ return {};
+ return createView(PP.RawEntry.data(), &__pn_.back());
+}
+
+string_view_t path::__parent_path() const {
+ if (empty())
+ return {};
+ // Determine if we have a root path but not a relative path. In that case
+ // return *this.
+ {
+ auto PP = PathParser::CreateBegin(__pn_);
+ if (ConsumeRootDir(&PP))
+ return __pn_;
+ }
+ // Otherwise remove a single element from the end of the path, and return
+ // a string representing that path
+ {
+ auto PP = PathParser::CreateEnd(__pn_);
+ --PP;
+ if (PP.RawEntry.data() == __pn_.data())
+ return {};
+ --PP;
+ return createView(__pn_.data(), &PP.RawEntry.back());
+ }
+}
+
+string_view_t path::__filename() const {
+ if (empty())
+ return {};
+ {
+ PathParser PP = PathParser::CreateBegin(__pn_);
+ if (ConsumeRootDir(&PP))
+ return {};
+ }
+ return *(--PathParser::CreateEnd(__pn_));
+}
+
+string_view_t path::__stem() const {
+ return parser::separate_filename(__filename()).first;
+}
+
+string_view_t path::__extension() const {
+ return parser::separate_filename(__filename()).second;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.gen
+
+enum PathPartKind : unsigned char {
+ PK_None,
+ PK_RootSep,
+ PK_Filename,
+ PK_Dot,
+ PK_DotDot,
+ PK_TrailingSep
+};
+
+static PathPartKind ClassifyPathPart(string_view_t Part) {
+ if (Part.empty())
+ return PK_TrailingSep;
+ if (Part == ".")
+ return PK_Dot;
+ if (Part == "..")
+ return PK_DotDot;
+ if (Part == "/")
+ return PK_RootSep;
+ return PK_Filename;
+}
+
+path path::lexically_normal() const {
+ if (__pn_.empty())
+ return *this;
+
+ using PartKindPair = pair<string_view_t, PathPartKind>;
+ vector<PartKindPair> Parts;
+ // Guess as to how many elements the path has to avoid reallocating.
+ Parts.reserve(32);
+
+ // Track the total size of the parts as we collect them. This allows the
+ // resulting path to reserve the correct amount of memory.
+ size_t NewPathSize = 0;
+ auto AddPart = [&](PathPartKind K, string_view_t P) {
+ NewPathSize += P.size();
+ Parts.emplace_back(P, K);
+ };
+ auto LastPartKind = [&]() {
+ if (Parts.empty())
+ return PK_None;
+ return Parts.back().second;
+ };
+
+ bool MaybeNeedTrailingSep = false;
+ // Build a stack containing the remaining elements of the path, popping off
+ // elements which occur before a '..' entry.
+ for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) {
+ auto Part = *PP;
+ PathPartKind Kind = ClassifyPathPart(Part);
+ switch (Kind) {
+ case PK_Filename:
+ case PK_RootSep: {
+ // Add all non-dot and non-dot-dot elements to the stack of elements.
+ AddPart(Kind, Part);
+ MaybeNeedTrailingSep = false;
+ break;
+ }
+ case PK_DotDot: {
+ // Only push a ".." element if there are no elements preceding the "..",
+ // or if the preceding element is itself "..".
+ auto LastKind = LastPartKind();
+ if (LastKind == PK_Filename) {
+ NewPathSize -= Parts.back().first.size();
+ Parts.pop_back();
+ } else if (LastKind != PK_RootSep)
+ AddPart(PK_DotDot, "..");
+ MaybeNeedTrailingSep = LastKind == PK_Filename;
+ break;
+ }
+ case PK_Dot:
+ case PK_TrailingSep: {
+ MaybeNeedTrailingSep = true;
+ break;
+ }
+ case PK_None:
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+ // [fs.path.generic]p6.8: If the path is empty, add a dot.
+ if (Parts.empty())
+ return ".";
+
+ // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any
+ // trailing directory-separator.
+ bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename;
+
+ path Result;
+ Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep);
+ for (auto& PK : Parts)
+ Result /= PK.first;
+
+ if (NeedTrailingSep)
+ Result /= "";
+
+ return Result;
+}
+
+static int DetermineLexicalElementCount(PathParser PP) {
+ int Count = 0;
+ for (; PP; ++PP) {
+ auto Elem = *PP;
+ if (Elem == "..")
+ --Count;
+ else if (Elem != ".")
+ ++Count;
+ }
+ return Count;
+}
+
+path path::lexically_relative(const path& base) const {
+ { // perform root-name/root-directory mismatch checks
+ auto PP = PathParser::CreateBegin(__pn_);
+ auto PPBase = PathParser::CreateBegin(base.__pn_);
+ auto CheckIterMismatchAtBase = [&]() {
+ return PP.State != PPBase.State &&
+ (PP.inRootPath() || PPBase.inRootPath());
+ };
+ if (PP.State == PathParser::PS_InRootName &&
+ PPBase.State == PathParser::PS_InRootName) {
+ if (*PP != *PPBase)
+ return {};
+ } else if (CheckIterMismatchAtBase())
+ return {};
+
+ if (PP.inRootPath())
+ ++PP;
+ if (PPBase.inRootPath())
+ ++PPBase;
+ if (CheckIterMismatchAtBase())
+ return {};
+ }
+
+ // Find the first mismatching element
+ auto PP = PathParser::CreateBegin(__pn_);
+ auto PPBase = PathParser::CreateBegin(base.__pn_);
+ while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) {
+ ++PP;
+ ++PPBase;
+ }
+
+ // If there is no mismatch, return ".".
+ if (!PP && !PPBase)
+ return ".";
+
+ // Otherwise, determine the number of elements, 'n', which are not dot or
+ // dot-dot minus the number of dot-dot elements.
+ int ElemCount = DetermineLexicalElementCount(PPBase);
+ if (ElemCount < 0)
+ return {};
+
+ // return a path constructed with 'n' dot-dot elements, followed by the the
+ // elements of '*this' after the mismatch.
+ path Result;
+ // FIXME: Reserve enough room in Result that it won't have to re-allocate.
+ while (ElemCount--)
+ Result /= "..";
+ for (; PP; ++PP)
+ Result /= *PP;
+ return Result;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.comparisons
+int path::__compare(string_view_t __s) const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ auto PP2 = PathParser::CreateBegin(__s);
+ while (PP && PP2) {
+ int res = (*PP).compare(*PP2);
+ if (res != 0)
+ return res;
+ ++PP;
+ ++PP2;
+ }
+ if (PP.State == PP2.State && !PP)
+ return 0;
+ if (!PP)
+ return -1;
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.nonmembers
+size_t hash_value(const path& __p) noexcept {
+ auto PP = PathParser::CreateBegin(__p.native());
+ size_t hash_value = 0;
+ hash<string_view_t> hasher;
+ while (PP) {
+ hash_value = __hash_combine(hash_value, hasher(*PP));
+ ++PP;
+ }
+ return hash_value;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// path.itr
+path::iterator path::begin() const {
+ auto PP = PathParser::CreateBegin(__pn_);
+ iterator it;
+ it.__path_ptr_ = this;
+ it.__state_ = static_cast<path::iterator::_ParserState>(PP.State);
+ it.__entry_ = PP.RawEntry;
+ it.__stashed_elem_.__assign_view(*PP);
+ return it;
+}
+
+path::iterator path::end() const {
+ iterator it{};
+ it.__state_ = path::iterator::_AtEnd;
+ it.__path_ptr_ = this;
+ return it;
+}
+
+path::iterator& path::iterator::__increment() {
+ PathParser PP(__path_ptr_->native(), __entry_, __state_);
+ ++PP;
+ __state_ = static_cast<_ParserState>(PP.State);
+ __entry_ = PP.RawEntry;
+ __stashed_elem_.__assign_view(*PP);
+ return *this;
+}
+
+path::iterator& path::iterator::__decrement() {
+ PathParser PP(__path_ptr_->native(), __entry_, __state_);
+ --PP;
+ __state_ = static_cast<_ParserState>(PP.State);
+ __entry_ = PP.RawEntry;
+ __stashed_elem_.__assign_view(*PP);
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// directory entry definitions
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _LIBCPP_WIN32API
+error_code directory_entry::__do_refresh() noexcept {
+ __data_.__reset();
+ error_code failure_ec;
+
+ StatT full_st;
+ file_status st = detail::posix_lstat(__p_, full_st, &failure_ec);
+ if (!status_known(st)) {
+ __data_.__reset();
+ return failure_ec;
+ }
+
+ if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+ } else { // we have a symlink
+ __data_.__sym_perms_ = st.permissions();
+ // Get the information about the linked entity.
+ // Ignore errors from stat, since we don't want errors regarding symlink
+ // resolution to be reported to the user.
+ error_code ignored_ec;
+ st = detail::posix_stat(__p_, full_st, &ignored_ec);
+
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+
+ // If we failed to resolve the link, then only partially populate the
+ // cache.
+ if (!status_known(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
+ return error_code{};
+ }
+ // Otherwise, we resolved the link, potentially as not existing.
+ // That's OK.
+ __data_.__cache_type_ = directory_entry::_RefreshSymlink;
+ }
+
+ if (_VSTD_FS::is_regular_file(st))
+ __data_.__size_ = static_cast<uintmax_t>(full_st.st_size);
+
+ if (_VSTD_FS::exists(st)) {
+ __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink);
+
+ // Attempt to extract the mtime, and fail if it's not representable using
+ // file_time_type. For now we ignore the error, as we'll report it when
+ // the value is actually used.
+ error_code ignored_ec;
+ __data_.__write_time_ =
+ __extract_last_write_time(__p_, full_st, &ignored_ec);
+ }
+
+ return failure_ec;
+}
+#else
+error_code directory_entry::__do_refresh() noexcept {
+ __data_.__reset();
+ error_code failure_ec;
+
+ file_status st = _VSTD_FS::symlink_status(__p_, failure_ec);
+ if (!status_known(st)) {
+ __data_.__reset();
+ return failure_ec;
+ }
+
+ if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshNonSymlink;
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+ } else { // we have a symlink
+ __data_.__sym_perms_ = st.permissions();
+ // Get the information about the linked entity.
+ // Ignore errors from stat, since we don't want errors regarding symlink
+ // resolution to be reported to the user.
+ error_code ignored_ec;
+ st = _VSTD_FS::status(__p_, ignored_ec);
+
+ __data_.__type_ = st.type();
+ __data_.__non_sym_perms_ = st.permissions();
+
+ // If we failed to resolve the link, then only partially populate the
+ // cache.
+ if (!status_known(st)) {
+ __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved;
+ return error_code{};
+ }
+ __data_.__cache_type_ = directory_entry::_RefreshSymlink;
+ }
+
+ // FIXME: This is currently broken, and the implementation only a placeholder.
+ // We need to cache last_write_time, file_size, and hard_link_count here before
+ // the implementation actually works.
+
+ return failure_ec;
+}
+#endif
+
+_LIBCPP_END_NAMESPACE_FILESYSTEM
#include <deque>
#include <errno.h>
#include <exception>
+#include <filesystem>
#include <float.h>
#include <forward_list>
#include <fstream>
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// RUN: %build -I%libcxx_src_root/src/experimental/filesystem
-// RUN: %run
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-#include "filesystem_common.h"
-
-using namespace fs::detail;
-
-TEST_SUITE(directory_entry_mods_suite)
-
-TEST_CASE(last_write_time_not_representable_error) {
- using namespace fs;
- using namespace std::chrono;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
-
- TimeSpec ToTime;
- ToTime.tv_sec = std::numeric_limits<decltype(ToTime.tv_sec)>::max();
- ToTime.tv_nsec = duration_cast<nanoseconds>(seconds(1)).count() - 1;
-
- std::array<TimeSpec, 2> TS = {ToTime, ToTime};
-
- file_time_type old_time = last_write_time(file);
- directory_entry ent(file);
-
- file_time_type start_time = file_time_type::clock::now() - hours(1);
- last_write_time(file, start_time);
-
- TEST_CHECK(ent.last_write_time() == old_time);
-
- bool IsRepresentable = true;
- file_time_type rep_value;
- {
- std::error_code ec;
- TEST_REQUIRE(!set_file_times(file, TS, ec));
- ec.clear();
- rep_value = last_write_time(file, ec);
- IsRepresentable = !bool(ec);
- }
-
- if (!IsRepresentable) {
- std::error_code rec = GetTestEC();
- ent.refresh(rec);
- TEST_CHECK(!rec);
-
- const std::errc expected_err = std::errc::value_too_large;
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, expected_err));
-
- ec = GetTestEC();
- TEST_CHECK(last_write_time(file, ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, expected_err));
-
- ExceptionChecker CheckExcept(file, expected_err,
- "directory_entry::last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, CheckExcept,
- ent.last_write_time());
-
- } else {
- ent.refresh();
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == rep_value);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-// UNSUPPORTED: libcpp-no-exceptions
-
-// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
-// MODULES_DEFINES: _LIBCPP_DEBUG=0
-
-// <experimental/filesystem>
-
-// class path
-
-#define _LIBCPP_DEBUG 0
-#define _LIBCPP_DEBUG_USE_EXCEPTIONS
-#include <experimental/filesystem>
-#include <iterator>
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "filesystem_test_helper.hpp"
-
-namespace fs = std::experimental::filesystem;
-
-int main() {
- using namespace fs;
- using ExType = std::__libcpp_debug_exception;
- // Test incrementing/decrementing a singular iterator
- {
- path::iterator singular;
- try {
- ++singular;
- assert(false);
- } catch (ExType const&) {}
- try {
- --singular;
- assert(false);
- } catch (ExType const&) {}
- }
- // Test decrementing the begin iterator
- {
- path p("foo/bar");
- auto it = p.begin();
- try {
- --it;
- assert(false);
- } catch (ExType const&) {}
- ++it;
- ++it;
- try {
- ++it;
- assert(false);
- } catch (ExType const&) {}
- }
- // Test incrementing the end iterator
- {
- path p("foo/bar");
- auto it = p.end();
- try {
- ++it;
- assert(false);
- } catch (ExType const&) {}
- --it;
- --it;
- try {
- --it;
- assert(false);
- } catch (ExType const&) {}
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-#include <experimental/filesystem>
-#include <iterator>
-
-
-namespace fs = std::experimental::filesystem;
-
-int main() {
- using namespace fs;
- using RIt = std::reverse_iterator<path::iterator>;
-
- // expected-error-re@iterator:* {{static_assert failed{{.*}} "The specified iterator type cannot be used with reverse_iterator; Using stashing iterators with reverse_iterator causes undefined behavior"}}
- {
- RIt r;
- ((void)r);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// template <class Tp> struct __is_pathable
-
-// [path.req]
-// In addition to the requirements (5), function template parameters named
-// `Source` shall be one of:
-// * basic_string<_ECharT, _Traits, _Alloc>
-// * InputIterator with a value_type of _ECharT
-// * A character array, which points to a NTCTS after array-to-pointer decay.
-
-
-#include <experimental/filesystem>
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "min_allocator.h"
-#include "constexpr_char_traits.hpp"
-
-namespace fs = std::experimental::filesystem;
-
-using fs::__is_pathable;
-
-template <class Tp>
-struct Identity { typedef Tp type; };
-
-template <class Source>
-Identity<Source> CheckSourceType(Source const&);
-
-template <class Tp>
-using GetSourceType = typename decltype(CheckSourceType(std::declval<Tp>()))::type;
-
-template <class Tp, class Exp,
- class ExpQual = typename std::remove_const<Exp>::type>
-using CheckPass = std::is_same<ExpQual, GetSourceType<Tp>>;
-
-template <class Source>
-using CheckPassSource = std::integral_constant<bool,
- CheckPass<Source&, Source>::value &&
- CheckPass<Source const&, Source>::value &&
- CheckPass<Source&&, Source>::value &&
- CheckPass<Source const&&, Source>::value
- >;
-
-template <class CharT>
-struct MakeTestType {
- using value_type = CharT;
- using string_type = std::basic_string<CharT>;
- using string_type2 = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>;
- using string_view_type = std::basic_string_view<CharT>;
- using string_view_type2 = std::basic_string_view<CharT, constexpr_char_traits<CharT>>;
- using cstr_type = CharT* const;
- using const_cstr_type = const CharT*;
- using array_type = CharT[25];
- using const_array_type = const CharT[25];
- using iter_type = input_iterator<CharT*>;
- using bad_iter_type = input_iterator<signed char*>;
-
- template <class TestT>
- static void AssertPathable() {
- static_assert(__is_pathable<TestT>::value, "");
- static_assert(CheckPassSource<TestT>::value, "cannot pass as Source const&");
- ASSERT_SAME_TYPE(CharT, typename __is_pathable<TestT>::__char_type);
- }
-
- template <class TestT>
- static void AssertNotPathable() {
- static_assert(!__is_pathable<TestT>::value, "");
- }
-
- static void Test() {
- AssertPathable<string_type>();
- AssertPathable<string_type2>();
- AssertPathable<string_view_type>();
- AssertPathable<string_view_type2>();
- AssertPathable<cstr_type>();
- AssertPathable<const_cstr_type>();
- AssertPathable<array_type>();
- AssertPathable<const_array_type>();
- AssertPathable<iter_type>();
-
- AssertNotPathable<CharT>();
- AssertNotPathable<bad_iter_type>();
- AssertNotPathable<signed char*>();
- }
-};
-
-int main() {
- MakeTestType<char>::Test();
- MakeTestType<wchar_t>::Test();
- MakeTestType<char16_t>::Test();
- MakeTestType<char32_t>::Test();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03, c++11
-
-// <experimental/filesystem>
-
-// typedef TrivialClock file_time_type;
-
-// RUN: %build -I%libcxx_src_root/src/experimental/filesystem
-// RUN: %run
-
-#include <experimental/filesystem>
-#include <chrono>
-#include <type_traits>
-#include <limits>
-#include <cstddef>
-#include <cassert>
-
-#include "filesystem_common.h"
-
-#ifndef __SIZEOF_INT128__
-#define TEST_HAS_NO_INT128_T
-#endif
-
-using namespace std::chrono;
-namespace fs = std::experimental::filesystem;
-using fs::file_time_type;
-using fs::detail::time_util;
-
-#ifdef TEST_HAS_NO_INT128_T
-static_assert(sizeof(fs::file_time_type::rep) <= 8, "");
-#endif
-
-enum TestKind { TK_128Bit, TK_64Bit, TK_32Bit, TK_FloatingPoint };
-
-template <class TimeT>
-constexpr TestKind getTimeTTestKind() {
- if (sizeof(TimeT) == 8 && !std::is_floating_point<TimeT>::value)
- return TK_64Bit;
- else if (sizeof(TimeT) == 4 && !std::is_floating_point<TimeT>::value)
- return TK_32Bit;
- else if (std::is_floating_point<TimeT>::value)
- return TK_FloatingPoint;
- else
- assert(false && "test kind not supported");
-}
-template <class FileTimeT>
-constexpr TestKind getFileTimeTestKind() {
- using Rep = typename FileTimeT::rep;
- if (std::is_floating_point<Rep>::value)
- return TK_FloatingPoint;
- else if (sizeof(Rep) == 16)
- return TK_128Bit;
- else if (sizeof(Rep) == 8)
- return TK_64Bit;
- else
- assert(false && "test kind not supported");
-}
-
-template <class FileTimeT, class TimeT, class TimeSpecT,
- class Base = time_util<FileTimeT, TimeT, TimeSpecT>,
- TestKind = getTimeTTestKind<TimeT>(),
- TestKind = getFileTimeTestKind<FileTimeT>()>
-struct test_case;
-
-template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
-struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_128Bit>
- : public Base {
-
- using Base::convert_from_timespec;
- using Base::convert_to_timespec;
- using Base::is_representable;
- using Base::max_nsec;
- using Base::max_seconds;
- using Base::min_nsec_timespec;
- using Base::min_seconds;
-
- static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
- static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
-
- static constexpr bool test_timespec() {
- static_assert(is_representable(TimeSpecT{max_time_t, 0}), "");
- static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
- static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
- static_assert(is_representable(TimeSpecT{max_time_t, max_nsec}), "");
-
- static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
- static_assert(is_representable(TimeSpecT{min_time_t, 999999999}), "");
- static_assert(is_representable(TimeSpecT{min_time_t, 1000000000}), "");
- static_assert(is_representable(TimeSpecT{min_time_t, min_nsec_timespec}),
- "");
-
- return true;
- }
-
- static constexpr bool test_file_time_type() {
- // This kinda sucks. Oh well.
- static_assert(!Base::is_representable(FileTimeT::max()), "");
- static_assert(!Base::is_representable(FileTimeT::min()), "");
- return true;
- }
-
- static constexpr bool check_round_trip(TimeSpecT orig) {
- TimeSpecT new_ts = {};
- FileTimeT out = convert_from_timespec(orig);
- assert(convert_to_timespec(new_ts, out));
- return new_ts.tv_sec == orig.tv_sec && new_ts.tv_nsec == orig.tv_nsec;
- }
-
- static constexpr bool test_convert_timespec() {
- static_assert(check_round_trip({0, 0}), "");
- static_assert(check_round_trip({0, 1}), "");
- static_assert(check_round_trip({1, 1}), "");
- static_assert(check_round_trip({-1, 1}), "");
- static_assert(check_round_trip({max_time_t, max_nsec}), "");
- static_assert(check_round_trip({max_time_t, 123}), "");
- static_assert(check_round_trip({min_time_t, min_nsec_timespec}), "");
- static_assert(check_round_trip({min_time_t, 123}), "");
- return true;
- }
-
- static bool test() {
- static_assert(test_timespec(), "");
- static_assert(test_file_time_type(), "");
- static_assert(test_convert_timespec(), "");
- return true;
- }
-};
-
-template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
-struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit, TK_128Bit>
- : public test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_128Bit> {
-
-};
-
-template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
-struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_64Bit>
- : public Base {
-
- using Base::convert_from_timespec;
- using Base::is_representable;
- using Base::max_nsec;
- using Base::max_seconds;
- using Base::min_nsec_timespec;
- using Base::min_seconds;
-
- static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
- static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
-
- static constexpr bool test_timespec() {
- static_assert(is_representable(TimeSpecT{max_seconds, max_nsec}), "");
- static_assert(!is_representable(TimeSpecT{max_seconds + 1, 0}), "");
- static_assert(!is_representable(TimeSpecT{max_seconds, max_nsec + 1}), "");
- static_assert(!is_representable(TimeSpecT{max_time_t, 0}), "");
- static_assert(is_representable(TimeSpecT{min_seconds, 0}), "");
- static_assert(
- is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec}), "");
- static_assert(
- is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}),
- "");
- static_assert(
- !is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec - 1}),
- "");
- static_assert(!is_representable(TimeSpecT{min_time_t, 999999999}), "");
- return true;
- }
-
- static constexpr bool test_file_time_type() {
- static_assert(Base::is_representable(FileTimeT::max()), "");
- static_assert(Base::is_representable(FileTimeT::min()), "");
- return true;
- }
-
- static constexpr bool test_convert_timespec() {
- static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec}) ==
- FileTimeT::max(),
- "");
- static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec - 1}) <
- FileTimeT::max(),
- "");
- static_assert(convert_from_timespec(TimeSpecT{max_seconds - 1, 999999999}) <
- FileTimeT::max(),
- "");
- static_assert(convert_from_timespec(TimeSpecT{
- min_seconds - 1, min_nsec_timespec}) == FileTimeT::min(),
- "");
- static_assert(convert_from_timespec(
- TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) >
- FileTimeT::min(),
- "");
- static_assert(convert_from_timespec(TimeSpecT{min_seconds, 0}) >
- FileTimeT::min(),
- "");
- return true;
- }
-
- static bool test() {
- static_assert(test_timespec(), "");
- static_assert(test_file_time_type(), "");
- static_assert(test_convert_timespec(), "");
- return true;
- }
-};
-
-template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
-struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit, TK_64Bit>
- : public Base {
- static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
- static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
-
- using Base::convert_from_timespec;
- using Base::is_representable;
- using Base::max_nsec;
- using Base::max_seconds;
- using Base::min_nsec_timespec;
- using Base::min_seconds;
-
- static constexpr bool test_timespec() {
- static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
- static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
- static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
- return true;
- }
-
- static constexpr bool test_file_time_type() {
- static_assert(!is_representable(FileTimeT::max()), "");
- static_assert(!is_representable(FileTimeT::min()), "");
- static_assert(is_representable(FileTimeT(seconds(max_time_t))), "");
- static_assert(is_representable(FileTimeT(seconds(min_time_t))), "");
- return true;
- }
-
- static constexpr bool test_convert_timespec() {
- // FIXME add tests for 32 bit builds
- return true;
- }
-
- static bool test() {
- static_assert(test_timespec(), "");
- static_assert(test_file_time_type(), "");
- static_assert(test_convert_timespec(), "");
- return true;
- }
-};
-
-template <class FileTimeT, class TimeT, class TimeSpec, class Base,
- TestKind FileTimeTKind>
-struct test_case<FileTimeT, TimeT, TimeSpec, Base, TK_FloatingPoint,
- FileTimeTKind> : public Base {
-
- static bool test() { return true; }
-};
-
-template <class TimeT, class NSecT = long>
-struct TestTimeSpec {
- TimeT tv_sec;
- NSecT tv_nsec;
-};
-
-template <class Dur>
-struct TestClock {
- typedef Dur duration;
- typedef typename duration::rep rep;
- typedef typename duration::period period;
- typedef std::chrono::time_point<TestClock> time_point;
- static constexpr const bool is_steady = false;
-
- static time_point now() noexcept { return {}; }
-};
-
-template <class IntType, class Period = std::micro>
-using TestFileTimeT = time_point<TestClock<duration<IntType, Period> > >;
-
-int main() {
- { assert((test_case<file_time_type, time_t, struct timespec>::test())); }
- {
- assert((test_case<TestFileTimeT<int64_t>, int64_t,
- TestTimeSpec<int64_t, long> >::test()));
- }
- {
- assert((test_case<TestFileTimeT<long long>, int32_t,
- TestTimeSpec<int32_t, int32_t> >::test()));
- }
- {
- // Test that insane platforms like ppc64 linux, which use long double as time_t,
- // at least compile.
- assert((test_case<TestFileTimeT<long double>, double,
- TestTimeSpec<long double, long> >::test()));
- }
-#ifndef TEST_HAS_NO_INT128_T
- {
- assert((test_case<TestFileTimeT<__int128_t, std::nano>, int64_t,
- TestTimeSpec<int64_t, long> >::test()));
- }
- {
- assert((test_case<TestFileTimeT<__int128_t, std::nano>, int32_t,
- TestTimeSpec<int32_t, int32_t> >::test()));
- }
-#endif
-}
+++ /dev/null
-# Disable all of the filesystem tests if the correct feature is not available.
-if 'c++filesystem' not in config.available_features:
- config.unsupported = True
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++98, c++03
-
// <experimental/filesystem>
#include <experimental/filesystem>
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// RUN: %build -I%libcxx_src_root/src/filesystem
+// RUN: %run
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+#include "filesystem_common.h"
+
+using namespace fs::detail;
+
+TEST_SUITE(directory_entry_mods_suite)
+
+TEST_CASE(last_write_time_not_representable_error) {
+ using namespace fs;
+ using namespace std::chrono;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+
+ TimeSpec ToTime;
+ ToTime.tv_sec = std::numeric_limits<decltype(ToTime.tv_sec)>::max();
+ ToTime.tv_nsec = duration_cast<nanoseconds>(seconds(1)).count() - 1;
+
+ std::array<TimeSpec, 2> TS = {ToTime, ToTime};
+
+ file_time_type old_time = last_write_time(file);
+ directory_entry ent(file);
+
+ file_time_type start_time = file_time_type::clock::now() - hours(1);
+ last_write_time(file, start_time);
+
+ TEST_CHECK(ent.last_write_time() == old_time);
+
+ bool IsRepresentable = true;
+ file_time_type rep_value;
+ {
+ std::error_code ec;
+ TEST_REQUIRE(!set_file_times(file, TS, ec));
+ ec.clear();
+ rep_value = last_write_time(file, ec);
+ IsRepresentable = !bool(ec);
+ }
+
+ if (!IsRepresentable) {
+ std::error_code rec = GetTestEC();
+ ent.refresh(rec);
+ TEST_CHECK(!rec);
+
+ const std::errc expected_err = std::errc::value_too_large;
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, expected_err));
+
+ ec = GetTestEC();
+ TEST_CHECK(last_write_time(file, ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, expected_err));
+
+ ExceptionChecker CheckExcept(file, expected_err,
+ "directory_entry::last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, CheckExcept,
+ ent.last_write_time());
+
+ } else {
+ ent.refresh();
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == rep_value);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+// UNSUPPORTED: libcpp-no-exceptions
+
+// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
+// MODULES_DEFINES: _LIBCPP_DEBUG=0
+
+// <filesystem>
+
+// class path
+
+#define _LIBCPP_DEBUG 0
+#define _LIBCPP_DEBUG_USE_EXCEPTIONS
+#include "filesystem_include.hpp"
+#include <iterator>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.hpp"
+
+int main() {
+ using namespace fs;
+ using ExType = std::__libcpp_debug_exception;
+ // Test incrementing/decrementing a singular iterator
+ {
+ path::iterator singular;
+ try {
+ ++singular;
+ assert(false);
+ } catch (ExType const&) {}
+ try {
+ --singular;
+ assert(false);
+ } catch (ExType const&) {}
+ }
+ // Test decrementing the begin iterator
+ {
+ path p("foo/bar");
+ auto it = p.begin();
+ try {
+ --it;
+ assert(false);
+ } catch (ExType const&) {}
+ ++it;
+ ++it;
+ try {
+ ++it;
+ assert(false);
+ } catch (ExType const&) {}
+ }
+ // Test incrementing the end iterator
+ {
+ path p("foo/bar");
+ auto it = p.end();
+ try {
+ ++it;
+ assert(false);
+ } catch (ExType const&) {}
+ --it;
+ --it;
+ try {
+ --it;
+ assert(false);
+ } catch (ExType const&) {}
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+#include "filesystem_include.hpp"
+#include <iterator>
+
+
+int main() {
+ using namespace fs;
+ using RIt = std::reverse_iterator<path::iterator>;
+
+ // expected-error-re@iterator:* {{static_assert failed{{.*}} "The specified iterator type cannot be used with reverse_iterator; Using stashing iterators with reverse_iterator causes undefined behavior"}}
+ {
+ RIt r;
+ ((void)r);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// template <class Tp> struct __is_pathable
+
+// [path.req]
+// In addition to the requirements (5), function template parameters named
+// `Source` shall be one of:
+// * basic_string<_ECharT, _Traits, _Alloc>
+// * InputIterator with a value_type of _ECharT
+// * A character array, which points to a NTCTS after array-to-pointer decay.
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "min_allocator.h"
+#include "constexpr_char_traits.hpp"
+
+using fs::__is_pathable;
+
+template <class Tp>
+struct Identity { typedef Tp type; };
+
+template <class Source>
+Identity<Source> CheckSourceType(Source const&);
+
+template <class Tp>
+using GetSourceType = typename decltype(CheckSourceType(std::declval<Tp>()))::type;
+
+template <class Tp, class Exp,
+ class ExpQual = typename std::remove_const<Exp>::type>
+using CheckPass = std::is_same<ExpQual, GetSourceType<Tp>>;
+
+template <class Source>
+using CheckPassSource = std::integral_constant<bool,
+ CheckPass<Source&, Source>::value &&
+ CheckPass<Source const&, Source>::value &&
+ CheckPass<Source&&, Source>::value &&
+ CheckPass<Source const&&, Source>::value
+ >;
+
+template <class CharT>
+struct MakeTestType {
+ using value_type = CharT;
+ using string_type = std::basic_string<CharT>;
+ using string_type2 = std::basic_string<CharT, std::char_traits<CharT>, min_allocator<CharT>>;
+ using string_view_type = std::basic_string_view<CharT>;
+ using string_view_type2 = std::basic_string_view<CharT, constexpr_char_traits<CharT>>;
+ using cstr_type = CharT* const;
+ using const_cstr_type = const CharT*;
+ using array_type = CharT[25];
+ using const_array_type = const CharT[25];
+ using iter_type = input_iterator<CharT*>;
+ using bad_iter_type = input_iterator<signed char*>;
+
+ template <class TestT>
+ static void AssertPathable() {
+ static_assert(__is_pathable<TestT>::value, "");
+ static_assert(CheckPassSource<TestT>::value, "cannot pass as Source const&");
+ ASSERT_SAME_TYPE(CharT, typename __is_pathable<TestT>::__char_type);
+ }
+
+ template <class TestT>
+ static void AssertNotPathable() {
+ static_assert(!__is_pathable<TestT>::value, "");
+ }
+
+ static void Test() {
+ AssertPathable<string_type>();
+ AssertPathable<string_type2>();
+ AssertPathable<string_view_type>();
+ AssertPathable<string_view_type2>();
+ AssertPathable<cstr_type>();
+ AssertPathable<const_cstr_type>();
+ AssertPathable<array_type>();
+ AssertPathable<const_array_type>();
+ AssertPathable<iter_type>();
+
+ AssertNotPathable<CharT>();
+ AssertNotPathable<bad_iter_type>();
+ AssertNotPathable<signed char*>();
+ }
+};
+
+int main() {
+ MakeTestType<char>::Test();
+ MakeTestType<wchar_t>::Test();
+ MakeTestType<char16_t>::Test();
+ MakeTestType<char32_t>::Test();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+// <filesystem>
+
+// typedef TrivialClock file_time_type;
+
+// RUN: %build -I%libcxx_src_root/src/filesystem
+// RUN: %run
+
+#include <filesystem>
+#include <chrono>
+#include <type_traits>
+#include <limits>
+#include <cstddef>
+#include <cassert>
+
+#include "filesystem_common.h"
+
+#ifndef __SIZEOF_INT128__
+#define TEST_HAS_NO_INT128_T
+#endif
+
+using namespace std::chrono;
+namespace fs = std::__fs::filesystem;
+using fs::file_time_type;
+using fs::detail::time_util;
+
+#ifdef TEST_HAS_NO_INT128_T
+static_assert(sizeof(fs::file_time_type::rep) <= 8, "");
+#endif
+
+enum TestKind { TK_128Bit, TK_64Bit, TK_32Bit, TK_FloatingPoint };
+
+template <class TimeT>
+constexpr TestKind getTimeTTestKind() {
+ if (sizeof(TimeT) == 8 && !std::is_floating_point<TimeT>::value)
+ return TK_64Bit;
+ else if (sizeof(TimeT) == 4 && !std::is_floating_point<TimeT>::value)
+ return TK_32Bit;
+ else if (std::is_floating_point<TimeT>::value)
+ return TK_FloatingPoint;
+ else
+ assert(false && "test kind not supported");
+}
+template <class FileTimeT>
+constexpr TestKind getFileTimeTestKind() {
+ using Rep = typename FileTimeT::rep;
+ if (std::is_floating_point<Rep>::value)
+ return TK_FloatingPoint;
+ else if (sizeof(Rep) == 16)
+ return TK_128Bit;
+ else if (sizeof(Rep) == 8)
+ return TK_64Bit;
+ else
+ assert(false && "test kind not supported");
+}
+
+template <class FileTimeT, class TimeT, class TimeSpecT,
+ class Base = time_util<FileTimeT, TimeT, TimeSpecT>,
+ TestKind = getTimeTTestKind<TimeT>(),
+ TestKind = getFileTimeTestKind<FileTimeT>()>
+struct test_case;
+
+template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
+struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_128Bit>
+ : public Base {
+
+ using Base::convert_from_timespec;
+ using Base::convert_to_timespec;
+ using Base::is_representable;
+ using Base::max_nsec;
+ using Base::max_seconds;
+ using Base::min_nsec_timespec;
+ using Base::min_seconds;
+
+ static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
+ static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
+
+ static constexpr bool test_timespec() {
+ static_assert(is_representable(TimeSpecT{max_time_t, 0}), "");
+ static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
+ static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
+ static_assert(is_representable(TimeSpecT{max_time_t, max_nsec}), "");
+
+ static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
+ static_assert(is_representable(TimeSpecT{min_time_t, 999999999}), "");
+ static_assert(is_representable(TimeSpecT{min_time_t, 1000000000}), "");
+ static_assert(is_representable(TimeSpecT{min_time_t, min_nsec_timespec}),
+ "");
+
+ return true;
+ }
+
+ static constexpr bool test_file_time_type() {
+ // This kinda sucks. Oh well.
+ static_assert(!Base::is_representable(FileTimeT::max()), "");
+ static_assert(!Base::is_representable(FileTimeT::min()), "");
+ return true;
+ }
+
+ static constexpr bool check_round_trip(TimeSpecT orig) {
+ TimeSpecT new_ts = {};
+ FileTimeT out = convert_from_timespec(orig);
+ assert(convert_to_timespec(new_ts, out));
+ return new_ts.tv_sec == orig.tv_sec && new_ts.tv_nsec == orig.tv_nsec;
+ }
+
+ static constexpr bool test_convert_timespec() {
+ static_assert(check_round_trip({0, 0}), "");
+ static_assert(check_round_trip({0, 1}), "");
+ static_assert(check_round_trip({1, 1}), "");
+ static_assert(check_round_trip({-1, 1}), "");
+ static_assert(check_round_trip({max_time_t, max_nsec}), "");
+ static_assert(check_round_trip({max_time_t, 123}), "");
+ static_assert(check_round_trip({min_time_t, min_nsec_timespec}), "");
+ static_assert(check_round_trip({min_time_t, 123}), "");
+ return true;
+ }
+
+ static bool test() {
+ static_assert(test_timespec(), "");
+ static_assert(test_file_time_type(), "");
+ static_assert(test_convert_timespec(), "");
+ return true;
+ }
+};
+
+template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
+struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit, TK_128Bit>
+ : public test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_128Bit> {
+
+};
+
+template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
+struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_64Bit, TK_64Bit>
+ : public Base {
+
+ using Base::convert_from_timespec;
+ using Base::is_representable;
+ using Base::max_nsec;
+ using Base::max_seconds;
+ using Base::min_nsec_timespec;
+ using Base::min_seconds;
+
+ static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
+ static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
+
+ static constexpr bool test_timespec() {
+ static_assert(is_representable(TimeSpecT{max_seconds, max_nsec}), "");
+ static_assert(!is_representable(TimeSpecT{max_seconds + 1, 0}), "");
+ static_assert(!is_representable(TimeSpecT{max_seconds, max_nsec + 1}), "");
+ static_assert(!is_representable(TimeSpecT{max_time_t, 0}), "");
+ static_assert(is_representable(TimeSpecT{min_seconds, 0}), "");
+ static_assert(
+ is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec}), "");
+ static_assert(
+ is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}),
+ "");
+ static_assert(
+ !is_representable(TimeSpecT{min_seconds - 1, min_nsec_timespec - 1}),
+ "");
+ static_assert(!is_representable(TimeSpecT{min_time_t, 999999999}), "");
+ return true;
+ }
+
+ static constexpr bool test_file_time_type() {
+ static_assert(Base::is_representable(FileTimeT::max()), "");
+ static_assert(Base::is_representable(FileTimeT::min()), "");
+ return true;
+ }
+
+ static constexpr bool test_convert_timespec() {
+ static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec}) ==
+ FileTimeT::max(),
+ "");
+ static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec - 1}) <
+ FileTimeT::max(),
+ "");
+ static_assert(convert_from_timespec(TimeSpecT{max_seconds - 1, 999999999}) <
+ FileTimeT::max(),
+ "");
+ static_assert(convert_from_timespec(TimeSpecT{
+ min_seconds - 1, min_nsec_timespec}) == FileTimeT::min(),
+ "");
+ static_assert(convert_from_timespec(
+ TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) >
+ FileTimeT::min(),
+ "");
+ static_assert(convert_from_timespec(TimeSpecT{min_seconds, 0}) >
+ FileTimeT::min(),
+ "");
+ return true;
+ }
+
+ static bool test() {
+ static_assert(test_timespec(), "");
+ static_assert(test_file_time_type(), "");
+ static_assert(test_convert_timespec(), "");
+ return true;
+ }
+};
+
+template <class FileTimeT, class TimeT, class TimeSpecT, class Base>
+struct test_case<FileTimeT, TimeT, TimeSpecT, Base, TK_32Bit, TK_64Bit>
+ : public Base {
+ static constexpr auto max_time_t = std::numeric_limits<TimeT>::max();
+ static constexpr auto min_time_t = std::numeric_limits<TimeT>::min();
+
+ using Base::convert_from_timespec;
+ using Base::is_representable;
+ using Base::max_nsec;
+ using Base::max_seconds;
+ using Base::min_nsec_timespec;
+ using Base::min_seconds;
+
+ static constexpr bool test_timespec() {
+ static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), "");
+ static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), "");
+ static_assert(is_representable(TimeSpecT{min_time_t, 0}), "");
+ return true;
+ }
+
+ static constexpr bool test_file_time_type() {
+ static_assert(!is_representable(FileTimeT::max()), "");
+ static_assert(!is_representable(FileTimeT::min()), "");
+ static_assert(is_representable(FileTimeT(seconds(max_time_t))), "");
+ static_assert(is_representable(FileTimeT(seconds(min_time_t))), "");
+ return true;
+ }
+
+ static constexpr bool test_convert_timespec() {
+ // FIXME add tests for 32 bit builds
+ return true;
+ }
+
+ static bool test() {
+ static_assert(test_timespec(), "");
+ static_assert(test_file_time_type(), "");
+ static_assert(test_convert_timespec(), "");
+ return true;
+ }
+};
+
+template <class FileTimeT, class TimeT, class TimeSpec, class Base,
+ TestKind FileTimeTKind>
+struct test_case<FileTimeT, TimeT, TimeSpec, Base, TK_FloatingPoint,
+ FileTimeTKind> : public Base {
+
+ static bool test() { return true; }
+};
+
+template <class TimeT, class NSecT = long>
+struct TestTimeSpec {
+ TimeT tv_sec;
+ NSecT tv_nsec;
+};
+
+template <class Dur>
+struct TestClock {
+ typedef Dur duration;
+ typedef typename duration::rep rep;
+ typedef typename duration::period period;
+ typedef std::chrono::time_point<TestClock> time_point;
+ static constexpr const bool is_steady = false;
+
+ static time_point now() noexcept { return {}; }
+};
+
+template <class IntType, class Period = std::micro>
+using TestFileTimeT = time_point<TestClock<duration<IntType, Period> > >;
+
+int main() {
+ { assert((test_case<file_time_type, time_t, struct timespec>::test())); }
+ {
+ assert((test_case<TestFileTimeT<int64_t>, int64_t,
+ TestTimeSpec<int64_t, long> >::test()));
+ }
+ {
+ assert((test_case<TestFileTimeT<long long>, int32_t,
+ TestTimeSpec<int32_t, int32_t> >::test()));
+ }
+ {
+ // Test that insane platforms like ppc64 linux, which use long double as time_t,
+ // at least compile.
+ assert((test_case<TestFileTimeT<long double>, double,
+ TestTimeSpec<long double, long> >::test()));
+ }
+#ifndef TEST_HAS_NO_INT128_T
+ {
+ assert((test_case<TestFileTimeT<__int128_t, std::nano>, int64_t,
+ TestTimeSpec<int64_t, long> >::test()));
+ }
+ {
+ assert((test_case<TestFileTimeT<__int128_t, std::nano>, int32_t,
+ TestTimeSpec<int32_t, int32_t> >::test()));
+ }
+#endif
+}
--- /dev/null
+# Disable all of the filesystem tests if the correct feature is not available.
+if 'c++filesystem' not in config.available_features:
+ config.unsupported = True
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <filesystem>
+
+#include <filesystem>
+
+#ifndef _LIBCPP_VERSION
+#error _LIBCPP_VERSION not defined
+#endif
+
+int main()
+{
+}
+++ /dev/null
-dne
\ No newline at end of file
+++ /dev/null
-dir3
\ No newline at end of file
+++ /dev/null
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
+++ /dev/null
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
+++ /dev/null
-dir1
\ No newline at end of file
+++ /dev/null
-empty_file
\ No newline at end of file
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry(const directory_entry&) = default;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-#include "test_convertible.hpp"
-
-TEST_SUITE(directory_entry_path_ctor_suite)
-
-TEST_CASE(copy_ctor) {
- using namespace fs;
- // Copy
- {
- static_assert(std::is_copy_constructible<directory_entry>::value,
- "directory_entry must be copy constructible");
- static_assert(!std::is_nothrow_copy_constructible<directory_entry>::value,
- "directory_entry's copy constructor cannot be noexcept");
- const path p("foo/bar/baz");
- const directory_entry e(p);
- assert(e.path() == p);
- directory_entry e2(e);
- assert(e.path() == p);
- assert(e2.path() == p);
- }
-}
-
-TEST_CASE(copy_ctor_copies_cache) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- {
- directory_entry ent(sym);
-
- fs::remove(sym);
-
- directory_entry ent_cp(ent);
- TEST_CHECK(ent_cp.path() == sym);
- TEST_CHECK(ent_cp.is_symlink());
- }
-
- {
- directory_entry ent(file);
-
- fs::remove(file);
-
- directory_entry ent_cp(ent);
- TEST_CHECK(ent_cp.path() == file);
- TEST_CHECK(ent_cp.is_regular_file());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry& operator=(directory_entry const&) = default;
-// directory_entry& operator=(directory_entry&&) noexcept = default;
-// void assign(path const&);
-// void replace_filename(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-TEST_SUITE(directory_entry_ctor_suite)
-
-TEST_CASE(test_copy_assign_operator) {
- using namespace fs;
- // Copy
- {
- static_assert(std::is_copy_assignable<directory_entry>::value,
- "directory_entry must be copy assignable");
- static_assert(!std::is_nothrow_copy_assignable<directory_entry>::value,
- "directory_entry's copy assignment cannot be noexcept");
- const path p("foo/bar/baz");
- const path p2("abc");
- const directory_entry e(p);
- directory_entry e2;
- assert(e.path() == p && e2.path() == path());
- e2 = e;
- assert(e.path() == p && e2.path() == p);
- directory_entry e3(p2);
- e2 = e3;
- assert(e2.path() == p2 && e3.path() == p2);
- }
-}
-
-TEST_CASE(copy_assign_copies_cache) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- {
- directory_entry ent(sym);
-
- fs::remove(sym);
-
- directory_entry ent_cp;
- ent_cp = ent;
- TEST_CHECK(ent_cp.path() == sym);
- TEST_CHECK(ent_cp.is_symlink());
- }
-
- {
- directory_entry ent(file);
-
- fs::remove(file);
-
- directory_entry ent_cp;
- ent_cp = ent;
- TEST_CHECK(ent_cp.path() == file);
- TEST_CHECK(ent_cp.is_regular_file());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry() noexcept = default;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-int main() {
- using namespace fs;
- // Default
- {
- static_assert(std::is_nothrow_default_constructible<directory_entry>::value,
- "directory_entry must have a nothrow default constructor");
- directory_entry e;
- assert(e.path() == path());
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-// XFAIL: apple-clang-7, clang-3.7, clang-3.8
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry() noexcept = default;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-int main() {
- using namespace fs;
- // Default
- {
- static_assert(std::is_nothrow_default_constructible<directory_entry>::value,
- "directory_entry must have a nothrow default constructor");
- const directory_entry e;
- assert(e.path() == path());
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry(directory_entry&&) noexcept = default;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-#include "test_convertible.hpp"
-
-TEST_SUITE(directory_entry_path_ctor_suite)
-
-TEST_CASE(move_ctor) {
- using namespace fs;
- // Move
- {
- static_assert(std::is_nothrow_move_constructible<directory_entry>::value,
- "directory_entry must be nothrow move constructible");
- const path p("foo/bar/baz");
- directory_entry e(p);
- assert(e.path() == p);
- directory_entry e2(std::move(e));
- assert(e2.path() == p);
- assert(e.path() != p); // Testing moved from state.
- }
-}
-
-TEST_CASE(move_ctor_copies_cache) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- {
- directory_entry ent(sym);
-
- fs::remove(sym);
-
- directory_entry ent_cp(std::move(ent));
- TEST_CHECK(ent_cp.path() == sym);
- TEST_CHECK(ent_cp.is_symlink());
- }
-
- {
- directory_entry ent(file);
-
- fs::remove(file);
-
- directory_entry ent_cp(std::move(ent));
- TEST_CHECK(ent_cp.path() == file);
- TEST_CHECK(ent_cp.is_regular_file());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry& operator=(directory_entry const&) = default;
-// directory_entry& operator=(directory_entry&&) noexcept = default;
-// void assign(path const&);
-// void replace_filename(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-TEST_SUITE(directory_entry_ctor_suite)
-
-TEST_CASE(test_move_assign_operator) {
- using namespace fs;
- // Copy
- {
- static_assert(std::is_nothrow_move_assignable<directory_entry>::value,
- "directory_entry is noexcept move assignable");
- const path p("foo/bar/baz");
- const path p2("abc");
- directory_entry e(p);
- directory_entry e2(p2);
- assert(e.path() == p && e2.path() == p2);
- e2 = std::move(e);
- assert(e2.path() == p);
- assert(e.path() != p); // testing moved from state
- }
-}
-
-TEST_CASE(move_assign_copies_cache) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- {
- directory_entry ent(sym);
-
- fs::remove(sym);
-
- directory_entry ent_cp;
- ent_cp = std::move(ent);
- TEST_CHECK(ent_cp.path() == sym);
- TEST_CHECK(ent_cp.is_symlink());
- }
-
- {
- directory_entry ent(file);
-
- fs::remove(file);
-
- directory_entry ent_cp;
- ent_cp = std::move(ent);
- TEST_CHECK(ent_cp.path() == file);
- TEST_CHECK(ent_cp.is_regular_file());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// explicit directory_entry(const path);
-// directory_entry(const path&, error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-#include "test_convertible.hpp"
-
-TEST_SUITE(directory_entry_path_ctor_suite)
-
-TEST_CASE(path_ctor) {
- using namespace fs;
- {
- static_assert(std::is_constructible<directory_entry, const path&>::value,
- "directory_entry must be constructible from path");
- static_assert(
- !std::is_nothrow_constructible<directory_entry, const path&>::value,
- "directory_entry constructor should not be noexcept");
- static_assert(!std::is_convertible<path const&, directory_entry>::value,
- "directory_entry constructor should be explicit");
- }
- {
- const path p("foo/bar/baz");
- const directory_entry e(p);
- TEST_CHECK(e.path() == p);
- }
-}
-
-TEST_CASE(path_ec_ctor) {
- using namespace fs;
- {
- static_assert(
- std::is_constructible<directory_entry, const path&,
- std::error_code&>::value,
- "directory_entry must be constructible from path and error_code");
- static_assert(!std::is_nothrow_constructible<directory_entry, const path&,
- std::error_code&>::value,
- "directory_entry constructor should not be noexcept");
- static_assert(
- test_convertible<directory_entry, const path&, std::error_code&>(),
- "directory_entry constructor should not be explicit");
- }
- {
- std::error_code ec = GetTestEC();
- const directory_entry e(StaticEnv::File, ec);
- TEST_CHECK(e.path() == StaticEnv::File);
- TEST_CHECK(!ec);
- }
- {
- const path p("foo/bar/baz");
- std::error_code ec = GetTestEC();
- const directory_entry e(p, ec);
- TEST_CHECK(e.path() == p);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- }
-}
-
-TEST_CASE(path_ctor_calls_refresh) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- {
- directory_entry ent(file);
- std::error_code ec = GetTestEC();
- directory_entry ent_ec(file, ec);
- TEST_CHECK(!ec);
-
- LIBCPP_ONLY(remove(file));
-
- TEST_CHECK(ent.exists());
- TEST_CHECK(ent_ec.exists());
-
- TEST_CHECK(ent.file_size() == 42);
- TEST_CHECK(ent_ec.file_size() == 42);
- }
-
- env.create_file("dir/file", 101);
-
- {
- directory_entry ent(sym);
- std::error_code ec = GetTestEC();
- directory_entry ent_ec(sym, ec);
- TEST_CHECK(!ec);
-
- LIBCPP_ONLY(remove(file));
- LIBCPP_ONLY(remove(sym));
-
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent_ec.is_symlink());
-
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent_ec.is_regular_file());
-
- TEST_CHECK(ent.file_size() == 101);
- TEST_CHECK(ent_ec.file_size() == 101);
- }
-}
-
-TEST_CASE(path_ctor_dne) {
- using namespace fs;
-
- {
- std::error_code ec = GetTestEC();
- directory_entry ent(StaticEnv::DNE, ec);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- TEST_CHECK(ent.path() == StaticEnv::DNE);
- }
- // don't report dead symlinks as an error.
- {
- std::error_code ec = GetTestEC();
- directory_entry ent(StaticEnv::BadSymlink, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ent.path() == StaticEnv::BadSymlink);
- }
- // DNE does not cause the constructor to throw
- {
- directory_entry ent(StaticEnv::DNE);
- TEST_CHECK(ent.path() == StaticEnv::DNE);
-
- directory_entry ent_two(StaticEnv::BadSymlink);
- TEST_CHECK(ent_two.path() == StaticEnv::BadSymlink);
- }
-}
-
-TEST_CASE(path_ctor_cannot_resolve) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file1", 101);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path sym_in_dir = env.create_symlink("dir/file1", "dir/sym2");
- permissions(dir, perms::none);
-
- {
- std::error_code ec = GetTestEC();
- directory_entry ent(file, ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- TEST_CHECK(ent.path() == file);
- }
- {
- std::error_code ec = GetTestEC();
- directory_entry ent(sym_in_dir, ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- TEST_CHECK(ent.path() == sym_in_dir);
- }
- {
- std::error_code ec = GetTestEC();
- directory_entry ent(sym_out_of_dir, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ent.path() == sym_out_of_dir);
- }
- {
- TEST_CHECK_NO_THROW(directory_entry(file));
- TEST_CHECK_NO_THROW(directory_entry(sym_in_dir));
- TEST_CHECK_NO_THROW(directory_entry(sym_out_of_dir));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry& operator=(directory_entry const&) = default;
-// directory_entry& operator=(directory_entry&&) noexcept = default;
-// void assign(path const&);
-// void replace_filename(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-TEST_SUITE(directory_entry_mods_suite)
-
-TEST_CASE(test_path_assign_method) {
- using namespace fs;
- const path p("foo/bar/baz");
- const path p2("abc");
- directory_entry e(p);
- {
- static_assert(std::is_same<decltype(e.assign(p)), void>::value,
- "return type should be void");
- static_assert(noexcept(e.assign(p)) == false,
- "operation must not be noexcept");
- }
- {
- TEST_CHECK(e.path() == p);
- e.assign(p2);
- TEST_CHECK(e.path() == p2 && e.path() != p);
- e.assign(p);
- TEST_CHECK(e.path() == p && e.path() != p2);
- }
-}
-
-TEST_CASE(test_path_assign_ec_method) {
- using namespace fs;
- const path p("foo/bar/baz");
- const path p2("abc");
- {
- std::error_code ec;
- directory_entry e(p);
- static_assert(std::is_same<decltype(e.assign(p, ec)), void>::value,
- "return type should be void");
- static_assert(noexcept(e.assign(p, ec)) == false,
- "operation must not be noexcept");
- }
- {
- directory_entry ent(p);
- std::error_code ec = GetTestEC();
- ent.assign(p2, ec);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- TEST_CHECK(ent.path() == p2);
- }
-}
-
-TEST_CASE(test_assign_calls_refresh) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- {
- directory_entry ent;
- ent.assign(file);
-
- // removing the file demonstrates that the values where cached previously.
- LIBCPP_ONLY(remove(file));
-
- TEST_CHECK(ent.is_regular_file());
- }
- env.create_file("dir/file", 101);
- {
- directory_entry ent;
- ent.assign(sym);
-
- LIBCPP_ONLY(remove(file));
- LIBCPP_ONLY(remove(sym));
-
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- }
-}
-
-TEST_CASE(test_assign_propagates_error) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path file_out_of_dir = env.create_file("file1");
- const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
-
- permissions(dir, perms::none);
-
- {
- directory_entry ent;
- std::error_code ec = GetTestEC();
- ent.assign(file, ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- }
- {
- directory_entry ent;
- std::error_code ec = GetTestEC();
- ent.assign(sym_in_dir, ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- }
- {
- directory_entry ent;
- std::error_code ec = GetTestEC();
- ent.assign(sym_out_of_dir, ec);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry& operator=(directory_entry const&) = default;
-// directory_entry& operator=(directory_entry&&) noexcept = default;
-// void assign(path const&);
-// void replace_filename(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-TEST_SUITE(directory_entry_mods_suite)
-
-TEST_CASE(test_refresh_method) {
- using namespace fs;
- {
- directory_entry e;
- static_assert(noexcept(e.refresh()) == false,
- "operation cannot be noexcept");
- static_assert(std::is_same<decltype(e.refresh()), void>::value,
- "operation must return void");
- }
- {
- directory_entry e;
- e.refresh();
- TEST_CHECK(!e.exists());
- }
-}
-
-TEST_CASE(test_refresh_ec_method) {
- using namespace fs;
- {
- directory_entry e;
- std::error_code ec;
- static_assert(noexcept(e.refresh(ec)), "operation should be noexcept");
- static_assert(std::is_same<decltype(e.refresh(ec)), void>::value,
- "operation must return void");
- }
- {
- directory_entry e;
- std::error_code ec = GetTestEC();
- e.refresh(ec);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- }
-}
-
-TEST_CASE(refresh_on_file_dne) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
-
- const perms old_perms = status(dir).permissions();
-
- // test file doesn't exist
- {
- directory_entry ent(file);
- remove(file);
- TEST_CHECK(ent.exists());
-
- ent.refresh();
-
- permissions(dir, perms::none);
- TEST_CHECK(!ent.exists());
- }
- permissions(dir, old_perms);
- env.create_file("dir/file", 101);
- {
- directory_entry ent(file);
- remove(file);
- TEST_CHECK(ent.exists());
-
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- permissions(dir, perms::none);
- TEST_CHECK(!ent.exists());
- }
-}
-
-void remove_if_exists(const fs::path& p) {
- std::error_code ec;
- remove(p, ec);
-}
-
-TEST_CASE(refresh_on_bad_symlink) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
-
- const perms old_perms = status(dir).permissions();
-
- // test file doesn't exist
- {
- directory_entry ent(sym);
- LIBCPP_ONLY(remove(file));
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.exists());
-
- remove_if_exists(file);
- ent.refresh();
-
- LIBCPP_ONLY(permissions(dir, perms::none));
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(!ent.is_regular_file());
- TEST_CHECK(!ent.exists());
- }
- permissions(dir, old_perms);
- env.create_file("dir/file", 101);
- {
- directory_entry ent(sym);
- LIBCPP_ONLY(remove(file));
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.exists());
-
- remove_if_exists(file);
-
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(!ec); // we don't report bad symlinks as an error.
-
- LIBCPP_ONLY(permissions(dir, perms::none));
- TEST_CHECK(!ent.exists());
- }
-}
-
-TEST_CASE(refresh_cannot_resolve) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file1", 99);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
- perms old_perms = status(dir).permissions();
-
- {
- directory_entry ent(file);
- permissions(dir, perms::none);
-
- TEST_CHECK(ent.is_regular_file());
-
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
-
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- TEST_CHECK(ent.path() == file);
-
- ExceptionChecker Checker(file, std::errc::permission_denied,
- "directory_entry::refresh");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh());
- }
- permissions(dir, old_perms);
- {
- directory_entry ent(sym_in_dir);
- permissions(dir, perms::none);
- TEST_CHECK(ent.is_symlink());
-
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- TEST_CHECK(ent.path() == sym_in_dir);
-
- ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
- "directory_entry::refresh");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh());
- }
- permissions(dir, old_perms);
- {
- directory_entry ent(sym_out_of_dir);
- permissions(dir, perms::none);
- TEST_CHECK(ent.is_symlink());
-
- // Failure to resolve the linked entity due to permissions is not
- // reported as an error.
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ent.is_symlink());
-
- ec = GetTestEC();
- TEST_CHECK(ent.exists(ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- TEST_CHECK(ent.path() == sym_out_of_dir);
- }
- permissions(dir, old_perms);
- {
- directory_entry ent_file(file);
- directory_entry ent_sym(sym_in_dir);
- directory_entry ent_sym2(sym_out_of_dir);
- permissions(dir, perms::none);
- ((void)ent_file);
- ((void)ent_sym);
-
- TEST_CHECK_THROW(filesystem_error, ent_file.refresh());
- TEST_CHECK_THROW(filesystem_error, ent_sym.refresh());
- TEST_CHECK_NO_THROW(ent_sym2);
- }
-}
-
-TEST_CASE(refresh_doesnt_throw_on_dne_but_reports_it) {
- using namespace fs;
- scoped_test_env env;
-
- const path file = env.create_file("file1", 42);
- const path sym = env.create_symlink("file1", "sym");
-
- {
- directory_entry ent(file);
- TEST_CHECK(ent.file_size() == 42);
-
- remove(file);
-
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- TEST_CHECK_NO_THROW(ent.refresh());
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- // doesn't throw!
- TEST_CHECK_THROW(filesystem_error, ent.file_size());
- }
- env.create_file("file1", 99);
- {
- directory_entry ent(sym);
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.file_size() == 99);
-
- remove(file);
-
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- TEST_CHECK_THROW(filesystem_error, ent.file_size());
- }
-}
-
-TEST_CASE(access_cache_after_refresh_fails) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file1", 101);
- const path sym = env.create_symlink("dir/file", "sym");
- const path sym_in_dir = env.create_symlink("dir/file", "dir/sym2");
-
- const perms old_perms = status(dir).permissions();
-
-#define CHECK_ACCESS(func, expect) \
- ec = GetTestEC(); \
- TEST_CHECK(ent.func(ec) == expect); \
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied))
-
- // test file doesn't exist
- {
- directory_entry ent(file);
-
- TEST_CHECK(!ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.exists());
-
- permissions(dir, perms::none);
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- CHECK_ACCESS(exists, false);
- CHECK_ACCESS(is_symlink, false);
- CHECK_ACCESS(last_write_time, file_time_type::min());
- CHECK_ACCESS(hard_link_count, uintmax_t(-1));
- }
- permissions(dir, old_perms);
- {
- directory_entry ent(sym_in_dir);
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.exists());
-
- permissions(dir, perms::none);
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- CHECK_ACCESS(exists, false);
- CHECK_ACCESS(is_symlink, false);
- CHECK_ACCESS(last_write_time, file_time_type::min());
- CHECK_ACCESS(hard_link_count, uintmax_t(-1));
- }
- permissions(dir, old_perms);
- {
- directory_entry ent(sym);
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.exists());
-
- permissions(dir, perms::none);
- std::error_code ec = GetTestEC();
- ent.refresh(ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ent.is_symlink());
-
- CHECK_ACCESS(exists, false);
- CHECK_ACCESS(is_regular_file, false);
- CHECK_ACCESS(last_write_time, file_time_type::min());
- CHECK_ACCESS(hard_link_count, uintmax_t(-1));
- }
-#undef CHECK_ACCESS
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// directory_entry& operator=(directory_entry const&) = default;
-// directory_entry& operator=(directory_entry&&) noexcept = default;
-// void assign(path const&);
-// void replace_filename(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-TEST_SUITE(directory_entry_mods_suite)
-
-TEST_CASE(test_replace_filename_method) {
- using namespace fs;
-
- {
- directory_entry e;
- path replace;
- static_assert(noexcept(e.replace_filename(replace)) == false,
- "operation cannot be noexcept");
- static_assert(
- std::is_same<decltype(e.replace_filename(replace)), void>::value,
- "operation must return void");
- }
- {
- const path p("/path/to/foo.exe");
- const path replace("bar.out");
- const path expect("/path/to/bar.out");
- directory_entry e(p);
- TEST_CHECK(e.path() == p);
- e.replace_filename(replace);
- TEST_CHECK(e.path() == expect);
- }
-}
-
-TEST_CASE(test_replace_filename_ec_method) {
- using namespace fs;
-
- {
- directory_entry e;
- path replace;
- std::error_code ec;
- static_assert(noexcept(e.replace_filename(replace, ec)) == false,
- "operation cannot be noexcept");
- static_assert(
- std::is_same<decltype(e.replace_filename(replace, ec)), void>::value,
- "operation must return void");
- }
- {
- const path p("/path/to/foo.exe");
- const path replace("bar.out");
- const path expect("/path/to/bar.out");
- directory_entry e(p);
- TEST_CHECK(e.path() == p);
- std::error_code ec = GetTestEC();
- e.replace_filename(replace, ec);
- TEST_CHECK(e.path() == expect);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- }
- {
- const path p = StaticEnv::EmptyFile;
- const path expect = StaticEnv::NonEmptyFile;
- const path replace = StaticEnv::NonEmptyFile.filename();
- TEST_REQUIRE(expect.parent_path() == p.parent_path());
- directory_entry e(p);
- TEST_CHECK(e.path() == p);
- std::error_code ec = GetTestEC();
- e.replace_filename(replace, ec);
- TEST_CHECK(e.path() == expect);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(test_replace_filename_calls_refresh) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_two = env.create_file("dir/file_two", 101);
- const path sym = env.create_symlink("dir/file", "sym");
- const path sym_two = env.create_symlink("dir/file_two", "sym_two");
-
- {
- directory_entry ent(file);
- ent.replace_filename(file_two.filename());
- TEST_REQUIRE(ent.path() == file_two);
-
- // removing the file demonstrates that the values where cached previously.
- LIBCPP_ONLY(remove(file_two));
-
- TEST_CHECK(ent.file_size() == 101);
- }
- env.create_file("dir/file_two", 99);
- {
- directory_entry ent(sym);
- ent.replace_filename(sym_two.filename());
- TEST_REQUIRE(ent.path() == sym_two);
-
- LIBCPP_ONLY(remove(file_two));
- LIBCPP_ONLY(remove(sym_two));
-
- TEST_CHECK(ent.is_symlink());
- TEST_CHECK(ent.is_regular_file());
- TEST_CHECK(ent.file_size() == 99);
- }
-}
-
-TEST_CASE(test_replace_filename_propagates_error) {
- using namespace fs;
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_two = env.create_file("dir/file_two", 99);
- const path file_out_of_dir = env.create_file("file_three", 101);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path sym_out_of_dir_two = env.create_symlink("dir/file", "sym_two");
- const path sym_in_dir = env.create_symlink("file_two", "dir/sym_three");
- const path sym_in_dir_two = env.create_symlink("file_two", "dir/sym_four");
-
- const perms old_perms = status(dir).permissions();
-
- {
- directory_entry ent(file);
- permissions(dir, perms::none);
- std::error_code ec = GetTestEC();
- ent.replace_filename(file_two.filename(), ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- }
- permissions(dir, old_perms);
- {
- directory_entry ent(sym_in_dir);
- permissions(dir, perms::none);
- std::error_code ec = GetTestEC();
- ent.replace_filename(sym_in_dir_two.filename(), ec);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- }
- permissions(dir, old_perms);
- {
- directory_entry ent(sym_out_of_dir);
- permissions(dir, perms::none);
- std::error_code ec = GetTestEC();
- ent.replace_filename(sym_out_of_dir_two.filename(), ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ent.is_symlink());
- ec = GetTestEC();
- TEST_CHECK(!ent.exists(ec));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// bool operator==(directory_entry const&) const noexcept;
-// bool operator!=(directory_entry const&) const noexcept;
-// bool operator< (directory_entry const&) const noexcept;
-// bool operator<=(directory_entry const&) const noexcept;
-// bool operator> (directory_entry const&) const noexcept;
-// bool operator>=(directory_entry const&) const noexcept;
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-
-#define CHECK_OP(Op) \
- static_assert(std::is_same<decltype(ce. operator Op (ce)), bool>::value, ""); \
- static_assert(noexcept(ce.operator Op (ce)), "Operation must be noexcept" )
-
-void test_comparison_signatures() {
- using namespace fs;
- path const p("foo/bar/baz");
- // Check that the operators are member functions with the correct signatures.
- {
- directory_entry const ce(p);
- CHECK_OP(==);
- CHECK_OP(!=);
- CHECK_OP(< );
- CHECK_OP(<=);
- CHECK_OP(> );
- CHECK_OP(>=);
- }
-}
-#undef CHECK_OP
-
-// The actual semantics of the comparisons are testing via paths operators.
-void test_comparisons_simple() {
- using namespace fs;
- typedef std::pair<path, path> TestType;
- TestType TestCases[] =
- {
- {"", ""},
- {"", "a"},
- {"a", "a"},
- {"a", "b"},
- {"foo/bar/baz", "foo/bar/baz/"}
- };
- auto TestFn = [](path const& LHS, const directory_entry& LHSE,
- path const& RHS, const directory_entry& RHSE) {
- assert((LHS == RHS) == (LHSE == RHSE));
- assert((LHS != RHS) == (LHSE != RHSE));
- assert((LHS < RHS) == (LHSE < RHSE));
- assert((LHS <= RHS) == (LHSE <= RHSE));
- assert((LHS > RHS) == (LHSE > RHSE));
- assert((LHS >= RHS) == (LHSE >= RHSE));
- };
- for (auto const& TC : TestCases) {
- const directory_entry L(TC.first);
- const directory_entry R(TC.second);
- TestFn(TC.first, L, TC.second, R);
- TestFn(TC.second, R, TC.first, L);
- }
-}
-
-int main() {
- test_comparison_signatures();
- test_comparisons_simple();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// uintmax_t file_size() const;
-// uintmax_t file_size(error_code const&) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "filesystem_test_helper.hpp"
-#include "rapid-cxx-test.hpp"
-
-#include <iostream>
-
-TEST_SUITE(directory_entry_obs_testsuite)
-
-TEST_CASE(signatures) {
- using namespace fs;
- {
- const fs::directory_entry e = {};
- std::error_code ec;
- static_assert(std::is_same<decltype(e.file_size()), uintmax_t>::value, "");
- static_assert(std::is_same<decltype(e.file_size(ec)), uintmax_t>::value,
- "");
- static_assert(noexcept(e.file_size()) == false, "");
- static_assert(noexcept(e.file_size(ec)) == true, "");
- }
-}
-
-TEST_CASE(basic) {
- using namespace fs;
-
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
- const path sym = env.create_symlink("file", "sym");
-
- {
- directory_entry ent(file);
- uintmax_t expect = file_size(ent);
- TEST_CHECK(expect == 42);
-
- // Remove the file to show that the results were already in the cache.
- LIBCPP_ONLY(remove(file));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == expect);
- TEST_CHECK(!ec);
- }
- env.create_file("file", 99);
- {
- directory_entry ent(sym);
-
- uintmax_t expect = file_size(ent);
- TEST_CHECK(expect == 99);
-
- LIBCPP_ONLY(remove(ent));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == 99);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(not_regular_file) {
- using namespace fs;
-
- scoped_test_env env;
- struct {
- const path p;
- std::errc expected_err;
- } TestCases[] = {
- {env.create_dir("dir"), std::errc::is_a_directory},
- {env.create_fifo("fifo"), std::errc::not_supported},
- {env.create_symlink("dir", "sym"), std::errc::is_a_directory}};
-
- for (auto const& TC : TestCases) {
- const path& p = TC.p;
- directory_entry ent(p);
- TEST_CHECK(ent.path() == p);
- std::error_code ec = GetTestEC(0);
-
- std::error_code other_ec = GetTestEC(1);
- uintmax_t expect = file_size(p, other_ec);
-
- uintmax_t got = ent.file_size(ec);
- TEST_CHECK(got == expect);
- TEST_CHECK(got == uintmax_t(-1));
- TEST_CHECK(ec == other_ec);
- TEST_CHECK(ErrorIs(ec, TC.expected_err));
-
- ExceptionChecker Checker(p, TC.expected_err, "directory_entry::file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
- }
-}
-
-TEST_CASE(error_reporting) {
- using namespace fs;
-
- scoped_test_env env;
-
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file2", 101);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
-
- const perms old_perms = status(dir).permissions();
-
- // test a file which doesn't exist
- {
- directory_entry ent;
-
- std::error_code ec = GetTestEC();
- ent.assign(StaticEnv::DNE, ec);
- TEST_REQUIRE(ent.path() == StaticEnv::DNE);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ExceptionChecker Checker(StaticEnv::DNE,
- std::errc::no_such_file_or_directory,
- "directory_entry::file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
- }
- // test a dead symlink
- {
- directory_entry ent;
-
- std::error_code ec = GetTestEC();
- uintmax_t expect_bad = file_size(StaticEnv::BadSymlink, ec);
- TEST_CHECK(expect_bad == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ec = GetTestEC();
- ent.assign(StaticEnv::BadSymlink, ec);
- TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == expect_bad);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ExceptionChecker Checker(StaticEnv::BadSymlink,
- std::errc::no_such_file_or_directory,
- "directory_entry::file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
- }
- // test a file w/o appropriate permissions.
- {
- directory_entry ent;
- uintmax_t expect_good = file_size(file);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(file, ec);
- TEST_REQUIRE(ent.path() == file);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(file, std::errc::permission_denied, "file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.file_size());
- }
- permissions(dir, old_perms);
- // test a symlink w/o appropriate permissions.
- {
- directory_entry ent;
- uintmax_t expect_good = file_size(sym_in_dir);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(sym_in_dir, ec);
- TEST_REQUIRE(ent.path() == sym_in_dir);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
- "file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.file_size());
- }
- permissions(dir, old_perms);
- // test a symlink to a file w/o appropriate permissions
- {
- directory_entry ent;
- uintmax_t expect_good = file_size(sym_out_of_dir);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(sym_out_of_dir, ec);
- TEST_REQUIRE(ent.path() == sym_out_of_dir);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
- "file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.file_size(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.file_size());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// file_status status() const;
-// file_status status(error_code const&) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "filesystem_test_helper.hpp"
-#include "rapid-cxx-test.hpp"
-
-TEST_SUITE(directory_entry_obs_testsuite)
-
-TEST_CASE(file_dne) {
- using namespace fs;
- directory_entry p("dne");
-}
-
-TEST_CASE(signatures) {
- using namespace fs;
- const directory_entry e = {};
- std::error_code ec;
-#define TEST_FUNC(name) \
- static_assert(std::is_same<decltype(e.name()), bool>::value, \
- "wrong return type"); \
- static_assert(noexcept(e.name()) == false, "should not be noexcept"); \
- static_assert(std::is_same<decltype(e.name(ec)), bool>::value, \
- "wrong return type"); \
- static_assert(noexcept(e.name(ec)) == true, "should be noexcept")
-
- TEST_FUNC(exists);
- TEST_FUNC(is_block_file);
- TEST_FUNC(is_character_file);
- TEST_FUNC(is_directory);
- TEST_FUNC(is_fifo);
- TEST_FUNC(is_other);
- TEST_FUNC(is_regular_file);
- TEST_FUNC(is_socket);
- TEST_FUNC(is_symlink);
-
-#undef TEST_FUNC
-}
-
-TEST_CASE(test_without_ec) {
- using namespace fs;
- using fs::directory_entry;
- using fs::file_status;
- using fs::path;
-
- scoped_test_env env;
- path f = env.create_file("foo", 42);
- path d = env.create_dir("dir");
- path fifo = env.create_fifo("fifo");
- path hl = env.create_hardlink("foo", "hl");
- for (auto p : {hl, f, d, fifo}) {
- directory_entry e(p);
- file_status st = status(p);
- file_status sym_st = symlink_status(p);
- fs::remove(p);
- TEST_REQUIRE(e.exists());
- TEST_REQUIRE(!exists(p));
- TEST_CHECK(e.exists() == exists(st));
- TEST_CHECK(e.is_block_file() == is_block_file(st));
- TEST_CHECK(e.is_character_file() == is_character_file(st));
- TEST_CHECK(e.is_directory() == is_directory(st));
- TEST_CHECK(e.is_fifo() == is_fifo(st));
- TEST_CHECK(e.is_other() == is_other(st));
- TEST_CHECK(e.is_regular_file() == is_regular_file(st));
- TEST_CHECK(e.is_socket() == is_socket(st));
- TEST_CHECK(e.is_symlink() == is_symlink(sym_st));
- }
-}
-
-TEST_CASE(test_with_ec) {
- using namespace fs;
- using fs::directory_entry;
- using fs::file_status;
- using fs::path;
-
- scoped_test_env env;
- path f = env.create_file("foo", 42);
- path d = env.create_dir("dir");
- path fifo = env.create_fifo("fifo");
- path hl = env.create_hardlink("foo", "hl");
- for (auto p : {hl, f, d, fifo}) {
- directory_entry e(p);
- std::error_code status_ec = GetTestEC();
- std::error_code sym_status_ec = GetTestEC(1);
- file_status st = status(p, status_ec);
- file_status sym_st = symlink_status(p, sym_status_ec);
- fs::remove(p);
- std::error_code ec = GetTestEC(2);
- auto CheckEC = [&](std::error_code const& other_ec) {
- bool res = ec == other_ec;
- ec = GetTestEC(2);
- return res;
- };
-
- TEST_REQUIRE(e.exists(ec));
- TEST_CHECK(CheckEC(status_ec));
- TEST_REQUIRE(!exists(p));
-
- TEST_CHECK(e.exists(ec) == exists(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_directory(ec) == is_directory(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_other(ec) == is_other(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_socket(ec) == is_socket(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
- TEST_CHECK(CheckEC(sym_status_ec));
- }
-}
-
-TEST_CASE(test_with_ec_dne) {
- using namespace fs;
- using fs::directory_entry;
- using fs::file_status;
- using fs::path;
-
- for (auto p : {StaticEnv::DNE, StaticEnv::BadSymlink}) {
-
- directory_entry e(p);
- std::error_code status_ec = GetTestEC();
- std::error_code sym_status_ec = GetTestEC(1);
- file_status st = status(p, status_ec);
- file_status sym_st = symlink_status(p, sym_status_ec);
- std::error_code ec = GetTestEC(2);
- auto CheckEC = [&](std::error_code const& other_ec) {
- bool res = ec == other_ec;
- ec = GetTestEC(2);
- return res;
- };
-
- TEST_CHECK(e.exists(ec) == exists(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_directory(ec) == is_directory(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_other(ec) == is_other(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_socket(ec) == is_socket(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
- TEST_CHECK(CheckEC(sym_status_ec));
- }
-}
-
-TEST_CASE(test_with_ec_cannot_resolve) {
- using namespace fs;
- using fs::directory_entry;
- using fs::file_status;
- using fs::path;
-
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file2", 99);
- const path sym = env.create_symlink("file2", "dir/sym");
-
- perms old_perms = fs::status(dir).permissions();
-
- for (auto p : {file, sym}) {
- permissions(dir, old_perms);
- directory_entry e(p);
-
- permissions(dir, perms::none);
- std::error_code dummy_ec;
- e.refresh(dummy_ec);
- TEST_REQUIRE(dummy_ec);
-
- std::error_code status_ec = GetTestEC();
- std::error_code sym_status_ec = GetTestEC(1);
- file_status st = status(p, status_ec);
- file_status sym_st = symlink_status(p, sym_status_ec);
- std::error_code ec = GetTestEC(2);
- auto CheckEC = [&](std::error_code const& other_ec) {
- bool res = ec == other_ec;
- ec = GetTestEC(2);
- return res;
- };
-
- TEST_CHECK(e.exists(ec) == exists(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_directory(ec) == is_directory(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_other(ec) == is_other(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_socket(ec) == is_socket(st));
- TEST_CHECK(CheckEC(status_ec));
-
- TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
- TEST_CHECK(CheckEC(sym_status_ec));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// uintmax_t hard_link_count() const;
-// uintmax_t hard_link_count(error_code const&) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "filesystem_test_helper.hpp"
-#include "rapid-cxx-test.hpp"
-
-TEST_SUITE(directory_entry_obs_testsuite)
-
-TEST_CASE(signatures) {
- using namespace fs;
- {
- const directory_entry e = {};
- std::error_code ec;
- static_assert(std::is_same<decltype(e.hard_link_count()), uintmax_t>::value, "");
- static_assert(std::is_same<decltype(e.hard_link_count(ec)), uintmax_t>::value,
- "");
- static_assert(noexcept(e.hard_link_count()) == false, "");
- static_assert(noexcept(e.hard_link_count(ec)) == true, "");
- }
-}
-
-TEST_CASE(basic) {
- using namespace fs;
-
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
- const path sym = env.create_symlink("file", "sym");
-
- {
- directory_entry ent(file);
- uintmax_t expect = hard_link_count(ent);
-
- // Remove the file to show that the results were already in the cache.
- LIBCPP_ONLY(remove(file));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect);
- TEST_CHECK(!ec);
- }
- {
- directory_entry ent(dir);
- uintmax_t expect = hard_link_count(ent);
-
- LIBCPP_ONLY(remove(dir));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect);
- TEST_CHECK(!ec);
- }
- env.create_file("file", 99);
- env.create_hardlink("file", "hl");
- {
- directory_entry ent(sym);
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == 2);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(not_regular_file) {
- using namespace fs;
-
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dir2 = env.create_dir("dir/dir2");
- const path fifo = env.create_fifo("dir/fifo");
- const path sym_to_fifo = env.create_symlink("dir/fifo", "dir/sym");
-
- const perms old_perms = status(dir).permissions();
-
- for (auto p : {dir2, fifo, sym_to_fifo}) {
- permissions(dir, old_perms);
- std::error_code dummy_ec = GetTestEC();
- directory_entry ent(p, dummy_ec);
- TEST_CHECK(!dummy_ec);
-
- uintmax_t expect = hard_link_count(p);
-
- LIBCPP_ONLY(permissions(dir, perms::none));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.hard_link_count());
- }
-}
-
-TEST_CASE(error_reporting) {
- using namespace fs;
-
- scoped_test_env env;
-
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file2", 101);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
-
- const perms old_perms = status(dir).permissions();
-
- // test a file which doesn't exist
- {
- directory_entry ent;
-
- std::error_code ec = GetTestEC();
- ent.assign(StaticEnv::DNE, ec);
- TEST_CHECK(ec);
- TEST_REQUIRE(ent.path() == StaticEnv::DNE);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ExceptionChecker Checker(StaticEnv::DNE,
- std::errc::no_such_file_or_directory,
- "directory_entry::hard_link_count");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
- }
- // test a dead symlink
- {
- directory_entry ent;
-
- std::error_code ec = GetTestEC();
- uintmax_t expect_bad = hard_link_count(StaticEnv::BadSymlink, ec);
- TEST_CHECK(expect_bad == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ec = GetTestEC();
- ent.assign(StaticEnv::BadSymlink, ec);
- TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect_bad);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ExceptionChecker Checker(StaticEnv::BadSymlink,
- std::errc::no_such_file_or_directory,
- "directory_entry::hard_link_count");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
- }
- // test a file w/o appropriate permissions.
- {
- directory_entry ent;
- uintmax_t expect_good = hard_link_count(file);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(file, ec);
- TEST_REQUIRE(ent.path() == file);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(file, std::errc::permission_denied,
- "hard_link_count");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.hard_link_count());
- }
- permissions(dir, old_perms);
- // test a symlink w/o appropriate permissions.
- {
- directory_entry ent;
- uintmax_t expect_good = hard_link_count(sym_in_dir);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(sym_in_dir, ec);
- TEST_REQUIRE(ent.path() == sym_in_dir);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
- "hard_link_count");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.hard_link_count());
- }
- permissions(dir, old_perms);
- // test a symlink to a file w/o appropriate permissions
- {
- directory_entry ent;
- uintmax_t expect_good = hard_link_count(sym_out_of_dir);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(sym_out_of_dir, ec);
- TEST_REQUIRE(ent.path() == sym_out_of_dir);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
- "hard_link_count");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.hard_link_count(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.hard_link_count());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// file_time_type last_write_time() const;
-// file_time_type last_write_time(error_code const&) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "filesystem_test_helper.hpp"
-#include "rapid-cxx-test.hpp"
-
-TEST_SUITE(directory_entry_obs_testsuite)
-
-TEST_CASE(signatures) {
- using namespace fs;
- {
- const fs::directory_entry e = {};
- std::error_code ec;
- static_assert(std::is_same<decltype(e.last_write_time()), file_time_type>::value,
- "");
- static_assert(std::is_same<decltype(e.last_write_time(ec)), file_time_type>::value,
- "");
- static_assert(noexcept(e.last_write_time()) == false, "");
- static_assert(noexcept(e.last_write_time(ec)) == true, "");
- }
-}
-
-TEST_CASE(basic) {
- using namespace fs;
-
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
- const path sym = env.create_symlink("file", "sym");
-
- {
- directory_entry ent(file);
- file_time_type expect = last_write_time(ent);
-
- // Remove the file to show that the results were already in the cache.
- LIBCPP_ONLY(remove(file));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect);
- TEST_CHECK(!ec);
- }
- {
- directory_entry ent(dir);
- file_time_type expect = last_write_time(ent);
-
- LIBCPP_ONLY(remove(dir));
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect);
- TEST_CHECK(!ec);
- }
- env.create_file("file", 99);
- {
- directory_entry ent(sym);
- file_time_type expect = last_write_time(sym);
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(error_reporting) {
- using namespace fs;
-
- scoped_test_env env;
-
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path file_out_of_dir = env.create_file("file2", 101);
- const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
- const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
-
- const perms old_perms = status(dir).permissions();
-
- // test a file which doesn't exist
- {
- directory_entry ent;
-
- std::error_code ec = GetTestEC();
- ent.assign(StaticEnv::DNE, ec);
- TEST_REQUIRE(ent.path() == StaticEnv::DNE);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ExceptionChecker Checker(StaticEnv::DNE,
- std::errc::no_such_file_or_directory,
- "directory_entry::last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
- }
- // test a dead symlink
- {
- directory_entry ent;
-
- std::error_code ec = GetTestEC();
- file_time_type expect_bad = last_write_time(StaticEnv::BadSymlink, ec);
- TEST_CHECK(expect_bad == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ec = GetTestEC();
- ent.assign(StaticEnv::BadSymlink, ec);
- TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect_bad);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-
- ExceptionChecker Checker(StaticEnv::BadSymlink,
- std::errc::no_such_file_or_directory,
- "directory_entry::last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
- }
- // test a file w/o appropriate permissions.
- {
- directory_entry ent;
- file_time_type expect_good = last_write_time(file);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(file, ec);
- TEST_REQUIRE(ent.path() == file);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(file, std::errc::permission_denied,
- "last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.last_write_time());
- }
- permissions(dir, old_perms);
- // test a symlink w/o appropriate permissions.
- {
- directory_entry ent;
- file_time_type expect_good = last_write_time(sym_in_dir);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(sym_in_dir, ec);
- TEST_REQUIRE(ent.path() == sym_in_dir);
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
- "last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.last_write_time());
- }
- permissions(dir, old_perms);
- // test a symlink to a file w/o appropriate permissions
- {
- directory_entry ent;
- file_time_type expect_good = last_write_time(sym_out_of_dir);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- ent.assign(sym_out_of_dir, ec);
- TEST_REQUIRE(ent.path() == sym_out_of_dir);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
- "last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
-
- permissions(dir, old_perms);
- ec = GetTestEC();
- TEST_CHECK(ent.last_write_time(ec) == expect_good);
- TEST_CHECK(!ec);
- TEST_CHECK_NO_THROW(ent.last_write_time());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// const path& path() const noexcept;
-// operator const path&() const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-
-void test_path_method() {
- using namespace fs;
- const path p("foo/bar/baz.exe");
- const path p2("abc");
- {
- directory_entry nce;
- const directory_entry e("");
- static_assert(std::is_same<decltype(e.path()), const path&>::value, "");
- static_assert(std::is_same<decltype(nce.path()), const path&>::value, "");
- static_assert(noexcept(e.path()) && noexcept(nce.path()), "");
- }
- {
- directory_entry e(p);
- path const& pref = e.path();
- assert(pref == p);
- assert(&pref == &e.path());
- e.assign(p2);
- assert(pref == p2);
- assert(&pref == &e.path());
- }
-}
-
-void test_path_conversion() {
- using namespace fs;
- const path p("foo/bar/baz.exe");
- const path p2("abc");
- {
- directory_entry nce;
- const directory_entry e("");
- // Check conversions exist
- static_assert(std::is_convertible<directory_entry&, path const&>::value, "");
- static_assert(std::is_convertible<directory_entry const&, path const&>::value, "");
- static_assert(std::is_convertible<directory_entry &&, path const&>::value, "");
- static_assert(std::is_convertible<directory_entry const&&, path const&>::value, "");
- // Not convertible to non-const
- static_assert(!std::is_convertible<directory_entry&, path&>::value, "");
- static_assert(!std::is_convertible<directory_entry const&, path&>::value, "");
- static_assert(!std::is_convertible<directory_entry &&, path&>::value, "");
- static_assert(!std::is_convertible<directory_entry const&&, path&>::value, "");
- // conversions are noexcept
- static_assert(noexcept(e.operator fs::path const&()) &&
- noexcept(e.operator fs::path const&()), "");
- }
- // const
- {
- directory_entry const e(p);
- path const& pref = e;
- assert(&pref == &e.path());
- }
- // non-const
- {
- directory_entry e(p);
- path const& pref = e;
- assert(&pref == &e.path());
-
- e.assign(p2);
- assert(pref == p2);
- assert(&pref == &e.path());
- }
-}
-
-int main() {
- test_path_method();
- test_path_conversion();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// file_status status() const;
-// file_status status(error_code const&) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "filesystem_test_helper.hpp"
-#include "rapid-cxx-test.hpp"
-
-TEST_SUITE(directory_entry_status_testsuite)
-
-TEST_CASE(test_basic) {
- using namespace fs;
- {
- const fs::directory_entry e("foo");
- std::error_code ec;
- static_assert(std::is_same<decltype(e.status()), fs::file_status>::value, "");
- static_assert(std::is_same<decltype(e.status(ec)), fs::file_status>::value, "");
- static_assert(noexcept(e.status()) == false, "");
- static_assert(noexcept(e.status(ec)) == true, "");
- }
- path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile,
- StaticEnv::DNE};
- for (const auto& p : TestCases) {
- const directory_entry e(p);
- std::error_code pec = GetTestEC(), eec = GetTestEC(1);
- file_status ps = fs::status(p, pec);
- file_status es = e.status(eec);
- TEST_CHECK(ps.type() == es.type());
- TEST_CHECK(ps.permissions() == es.permissions());
- TEST_CHECK(pec == eec);
- }
- for (const auto& p : TestCases) {
- const directory_entry e(p);
- file_status ps = fs::status(p);
- file_status es = e.status();
- TEST_CHECK(ps.type() == es.type());
- TEST_CHECK(ps.permissions() == es.permissions());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_entry
-
-// file_status symlink_status() const;
-// file_status symlink_status(error_code&) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "filesystem_test_helper.hpp"
-#include "rapid-cxx-test.hpp"
-
-TEST_SUITE(directory_entry_obs_suite)
-
-TEST_CASE(test_signature) {
- using namespace fs;
- {
- const directory_entry e("foo");
- std::error_code ec;
- static_assert(std::is_same<decltype(e.symlink_status()), file_status>::value, "");
- static_assert(std::is_same<decltype(e.symlink_status(ec)), file_status>::value, "");
- static_assert(noexcept(e.symlink_status()) == false, "");
- static_assert(noexcept(e.symlink_status(ec)) == true, "");
- }
- path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile,
- StaticEnv::DNE};
- for (const auto& p : TestCases) {
- const directory_entry e(p);
- std::error_code pec = GetTestEC(), eec = GetTestEC(1);
- file_status ps = fs::symlink_status(p, pec);
- file_status es = e.symlink_status(eec);
- TEST_CHECK(ps.type() == es.type());
- TEST_CHECK(ps.permissions() == es.permissions());
- TEST_CHECK(pec == eec);
- }
- for (const auto& p : TestCases) {
- const directory_entry e(p);
- file_status ps = fs::symlink_status(p);
- file_status es = e.symlink_status();
- TEST_CHECK(ps.type() == es.type());
- TEST_CHECK(ps.permissions() == es.permissions());
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator(directory_iterator const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_copy_construct_tests)
-
-TEST_CASE(test_constructor_signature)
-{
- using D = directory_iterator;
- static_assert(std::is_copy_constructible<D>::value, "");
-}
-
-TEST_CASE(test_copy_end_iterator)
-{
- const directory_iterator endIt;
- directory_iterator it(endIt);
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(test_copy_valid_iterator)
-{
- const path testDir = StaticEnv::Dir;
- const directory_iterator endIt{};
-
- const directory_iterator it(testDir);
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
-
- const directory_iterator it2(it);
- TEST_REQUIRE(it2 == it);
- TEST_CHECK(*it2 == entry);
- TEST_CHECK(*it == entry);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator& operator=(directory_iterator const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_copy_assign_tests)
-
-TEST_CASE(test_assignment_signature)
-{
- using D = directory_iterator;
- static_assert(std::is_copy_assignable<D>::value, "");
-}
-
-TEST_CASE(test_copy_to_end_iterator)
-{
- const path testDir = StaticEnv::Dir;
-
- const directory_iterator from(testDir);
- TEST_REQUIRE(from != directory_iterator{});
- const path entry = *from;
-
- directory_iterator to{};
- to = from;
- TEST_REQUIRE(to == from);
- TEST_CHECK(*to == entry);
- TEST_CHECK(*from == entry);
-}
-
-
-TEST_CASE(test_copy_from_end_iterator)
-{
- const path testDir = StaticEnv::Dir;
-
- const directory_iterator from{};
-
- directory_iterator to(testDir);
- TEST_REQUIRE(to != directory_iterator{});
-
- to = from;
- TEST_REQUIRE(to == from);
- TEST_CHECK(to == directory_iterator{});
-}
-
-TEST_CASE(test_copy_valid_iterator)
-{
- const path testDir = StaticEnv::Dir;
- const directory_iterator endIt{};
-
- directory_iterator it_obj(testDir);
- const directory_iterator& it = it_obj;
- TEST_REQUIRE(it != endIt);
- ++it_obj;
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
-
- directory_iterator it2(testDir);
- TEST_REQUIRE(it2 != it);
- const path entry2 = *it2;
- TEST_CHECK(entry2 != entry);
-
- it2 = it;
- TEST_REQUIRE(it2 == it);
- TEST_CHECK(*it2 == entry);
-}
-
-TEST_CASE(test_returns_reference_to_self)
-{
- const directory_iterator it;
- directory_iterator it2;
- directory_iterator& ref = (it2 = it);
- TEST_CHECK(&ref == &it2);
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// explicit directory_iterator(const path& p);
-// directory_iterator(const path& p, directory_options options);
-// directory_iterator(const path& p, error_code& ec);
-// directory_iterator(const path& p, directory_options options, error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_constructor_tests)
-
-TEST_CASE(test_constructor_signatures)
-{
- using D = directory_iterator;
-
- // explicit directory_iterator(path const&);
- static_assert(!std::is_convertible<path, D>::value, "");
- static_assert(std::is_constructible<D, path>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path>::value, "");
-
- // directory_iterator(path const&, error_code&)
- static_assert(std::is_constructible<D, path,
- std::error_code&>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path,
- std::error_code&>::value, "");
-
- // directory_iterator(path const&, directory_options);
- static_assert(std::is_constructible<D, path, directory_options>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
-
- // directory_iterator(path const&, directory_options, error_code&)
- static_assert(std::is_constructible<D, path, directory_options,
- std::error_code&>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path, directory_options,
- std::error_code&>::value, "");
-
-}
-
-TEST_CASE(test_construction_from_bad_path)
-{
- std::error_code ec;
- directory_options opts = directory_options::none;
- const directory_iterator endIt;
-
- const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink };
- for (path const& testPath : testPaths)
- {
- {
- directory_iterator it(testPath, ec);
- TEST_CHECK(ec);
- TEST_CHECK(it == endIt);
- }
- {
- directory_iterator it(testPath, opts, ec);
- TEST_CHECK(ec);
- TEST_CHECK(it == endIt);
- }
- {
- TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath));
- TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath, opts));
- }
- }
-}
-
-TEST_CASE(access_denied_test_case)
-{
- using namespace fs;
- scoped_test_env env;
- path const testDir = env.make_env_path("dir1");
- path const testFile = testDir / "testFile";
- env.create_dir(testDir);
- env.create_file(testFile, 42);
-
- // Test that we can iterator over the directory before changing the perms
- {
- directory_iterator it(testDir);
- TEST_REQUIRE(it != directory_iterator{});
- }
- // Change the permissions so we can no longer iterate
- permissions(testDir, perms::none);
-
- // Check that the construction fails when skip_permissions_denied is
- // not given.
- {
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == directory_iterator{});
- }
- // Check that construction does not report an error when
- // 'skip_permissions_denied' is given.
- {
- std::error_code ec;
- directory_iterator it(testDir, directory_options::skip_permission_denied, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it == directory_iterator{});
- }
-}
-
-
-TEST_CASE(access_denied_to_file_test_case)
-{
- using namespace fs;
- scoped_test_env env;
- path const testFile = env.make_env_path("file1");
- env.create_file(testFile, 42);
-
- // Change the permissions so we can no longer iterate
- permissions(testFile, perms::none);
-
- // Check that the construction fails when skip_permissions_denied is
- // not given.
- {
- std::error_code ec;
- directory_iterator it(testFile, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == directory_iterator{});
- }
- // Check that construction still fails when 'skip_permissions_denied' is given
- // because we tried to open a file and not a directory.
- {
- std::error_code ec;
- directory_iterator it(testFile, directory_options::skip_permission_denied, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == directory_iterator{});
- }
-}
-
-TEST_CASE(test_open_on_empty_directory_equals_end)
-{
- scoped_test_env env;
- const path testDir = env.make_env_path("dir1");
- env.create_dir(testDir);
-
- const directory_iterator endIt;
- {
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(it == endIt);
- }
- {
- directory_iterator it(testDir);
- TEST_CHECK(it == endIt);
- }
-}
-
-TEST_CASE(test_open_on_directory_succeeds)
-{
- const path testDir = StaticEnv::Dir;
- std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
- std::end( StaticEnv::DirIterationList));
- const directory_iterator endIt{};
-
- {
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it != endIt);
- TEST_CHECK(dir_contents.count(*it));
- }
- {
- directory_iterator it(testDir);
- TEST_CHECK(it != endIt);
- TEST_CHECK(dir_contents.count(*it));
- }
-}
-
-TEST_CASE(test_open_on_file_fails)
-{
- const path testFile = StaticEnv::File;
- const directory_iterator endIt{};
- {
- std::error_code ec;
- directory_iterator it(testFile, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == endIt);
- }
- {
- TEST_CHECK_THROW(filesystem_error, directory_iterator(testFile));
- }
-}
-
-TEST_CASE(test_open_on_empty_string)
-{
- const path testPath = "";
- const directory_iterator endIt{};
-
- std::error_code ec;
- directory_iterator it(testPath, ec);
- TEST_CHECK(ec);
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(test_open_on_dot_dir)
-{
- const path testPath = ".";
-
- std::error_code ec;
- directory_iterator it(testPath, ec);
- TEST_CHECK(!ec);
-}
-
-TEST_CASE(test_open_on_symlink)
-{
- const path symlinkToDir = StaticEnv::SymlinkToDir;
- std::set<path> dir_contents;
- for (path const& p : StaticEnv::DirIterationList) {
- dir_contents.insert(p.filename());
- }
- const directory_iterator endIt{};
-
- {
- std::error_code ec;
- directory_iterator it(symlinkToDir, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it != endIt);
- path const& entry = *it;
- TEST_CHECK(dir_contents.count(entry.filename()));
- }
- {
- std::error_code ec;
- directory_iterator it(symlinkToDir,
- directory_options::follow_directory_symlink, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it != endIt);
- path const& entry = *it;
- TEST_CHECK(dir_contents.count(entry.filename()));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator::directory_iterator() noexcept
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-int main() {
- {
- static_assert(std::is_nothrow_default_constructible<fs::directory_iterator>::value, "");
- }
- {
- fs::directory_iterator d1;
- const fs::directory_iterator d2;
- assert(d1 == d2);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator& operator++();
-// directory_iterator& increment(error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-#include <iostream>
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_increment_tests)
-
-TEST_CASE(test_increment_signatures)
-{
- using D = directory_iterator;
- directory_iterator d; ((void)d);
- std::error_code ec; ((void)ec);
-
- ASSERT_SAME_TYPE(decltype(++d), directory_iterator&);
- ASSERT_NOT_NOEXCEPT(++d);
-
- ASSERT_SAME_TYPE(decltype(d.increment(ec)), directory_iterator&);
- ASSERT_NOT_NOEXCEPT(d.increment(ec));
-}
-
-TEST_CASE(test_prefix_increment)
-{
- const path testDir = StaticEnv::Dir;
- const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
- std::end( StaticEnv::DirIterationList));
- const directory_iterator endIt{};
-
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- directory_iterator& it_ref = ++it;
- TEST_CHECK(&it_ref == &it);
- }
-
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(test_postfix_increment)
-{
- const path testDir = StaticEnv::Dir;
- const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
- std::end( StaticEnv::DirIterationList));
- const directory_iterator endIt{};
-
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- const path entry2 = *it++;
- TEST_CHECK(entry2 == entry);
- }
-
- TEST_CHECK(it == endIt);
-}
-
-
-TEST_CASE(test_increment_method)
-{
- const path testDir = StaticEnv::Dir;
- const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
- std::end( StaticEnv::DirIterationList));
- const directory_iterator endIt{};
-
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- directory_iterator& it_ref = it.increment(ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(&it_ref == &it);
- }
-
- TEST_CHECK(it == endIt);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator(directory_iterator&&) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_move_construct_tests)
-
-TEST_CASE(test_constructor_signature)
-{
- using D = directory_iterator;
- static_assert(std::is_nothrow_move_constructible<D>::value, "");
-}
-
-TEST_CASE(test_move_end_iterator)
-{
- const directory_iterator endIt;
- directory_iterator endIt2{};
-
- directory_iterator it(std::move(endIt2));
- TEST_CHECK(it == endIt);
- TEST_CHECK(endIt2 == endIt);
-}
-
-TEST_CASE(test_move_valid_iterator)
-{
- const path testDir = StaticEnv::Dir;
- const directory_iterator endIt{};
-
- directory_iterator it(testDir);
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
-
- const directory_iterator it2(std::move(it));
- TEST_CHECK(*it2 == entry);
-
- TEST_CHECK(it == it2 || it == endIt);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator& operator=(directory_iterator const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-// The filesystem specification explicitly allows for self-move on
-// the directory iterators. Turn off this warning so we can test it.
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wself-move"
-#endif
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_move_assign_tests)
-
-TEST_CASE(test_assignment_signature)
-{
- using D = directory_iterator;
- static_assert(std::is_nothrow_move_assignable<D>::value, "");
-}
-
-TEST_CASE(test_move_to_end_iterator)
-{
- const path testDir = StaticEnv::Dir;
-
- directory_iterator from(testDir);
- TEST_REQUIRE(from != directory_iterator{});
- const path entry = *from;
-
- directory_iterator to{};
- to = std::move(from);
- TEST_REQUIRE(to != directory_iterator{});
- TEST_CHECK(*to == entry);
-}
-
-
-TEST_CASE(test_move_from_end_iterator)
-{
- const path testDir = StaticEnv::Dir;
-
- directory_iterator from{};
-
- directory_iterator to(testDir);
- TEST_REQUIRE(to != from);
-
- to = std::move(from);
- TEST_REQUIRE(to == directory_iterator{});
- TEST_REQUIRE(from == directory_iterator{});
-}
-
-TEST_CASE(test_move_valid_iterator)
-{
- const path testDir = StaticEnv::Dir;
- const directory_iterator endIt{};
-
- directory_iterator it(testDir);
- TEST_REQUIRE(it != endIt);
- ++it;
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
-
- directory_iterator it2(testDir);
- TEST_REQUIRE(it2 != it);
- const path entry2 = *it2;
- TEST_CHECK(entry2 != entry);
-
- it2 = std::move(it);
- TEST_REQUIRE(it2 != directory_iterator{});
- TEST_CHECK(*it2 == entry);
-}
-
-TEST_CASE(test_returns_reference_to_self)
-{
- directory_iterator it;
- directory_iterator it2;
- directory_iterator& ref = (it2 = it);
- TEST_CHECK(&ref == &it2);
-}
-
-
-TEST_CASE(test_self_move)
-{
- // Create two non-equal iterators that have exactly the same state.
- directory_iterator it(StaticEnv::Dir);
- directory_iterator it2(StaticEnv::Dir);
- ++it; ++it2;
- TEST_CHECK(it != it2);
- TEST_CHECK(*it2 == *it);
-
- it = std::move(it);
- TEST_CHECK(*it2 == *it);
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// directory_iterator begin(directory_iterator iter) noexcept;
-// directory_iterator end(directory_iterator iter) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-#include <iostream>
-
-using namespace fs;
-
-TEST_SUITE(directory_iterator_begin_end_tests)
-
-TEST_CASE(test_function_signatures)
-{
- using D = directory_iterator;
- directory_iterator d; ((void)d);
-
- ASSERT_SAME_TYPE(decltype(begin(d)), directory_iterator);
- ASSERT_NOEXCEPT(begin(std::move(d)));
-
- ASSERT_SAME_TYPE(decltype(end(d)), directory_iterator);
- ASSERT_NOEXCEPT(end(std::move(d)));
-}
-
-TEST_CASE(test_ranged_for_loop)
-{
- const path testDir = StaticEnv::Dir;
- std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
- std::end( StaticEnv::DirIterationList));
-
- std::error_code ec;
- directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- for (auto& elem : it) {
- TEST_CHECK(dir_contents.erase(elem) == 1);
- }
- TEST_CHECK(dir_contents.empty());
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-// typedef ... value_type;
-// typedef ... difference_type;
-// typedef ... pointer;
-// typedef ... reference;
-// typedef ... iterator_category
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-int main() {
- using namespace fs;
- using D = directory_iterator;
- ASSERT_SAME_TYPE(D::value_type, directory_entry);
- ASSERT_SAME_TYPE(D::difference_type, std::ptrdiff_t);
- ASSERT_SAME_TYPE(D::pointer, const directory_entry*);
- ASSERT_SAME_TYPE(D::reference, const directory_entry&);
- ASSERT_SAME_TYPE(D::iterator_category, std::input_iterator_tag);
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class file_status
-
-// explicit file_status() noexcept;
-// explicit file_status(file_type, perms prms = perms::unknown) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_convertible.hpp"
-
-
-int main() {
- using namespace fs;
- // Default ctor
- {
- static_assert(std::is_nothrow_default_constructible<file_status>::value,
- "The default constructor must be noexcept");
- static_assert(test_convertible<file_status>(),
- "The default constructor must not be explicit");
- const file_status f;
- assert(f.type() == file_type::none);
- assert(f.permissions() == perms::unknown);
- }
-
- // Unary ctor
- {
- static_assert(std::is_nothrow_constructible<file_status, file_type>::value,
- "This constructor must be noexcept");
- static_assert(!test_convertible<file_status, file_type>(),
- "This constructor must be explicit");
-
- const file_status f(file_type::not_found);
- assert(f.type() == file_type::not_found);
- assert(f.permissions() == perms::unknown);
- }
- // Binary ctor
- {
- static_assert(std::is_nothrow_constructible<file_status, file_type, perms>::value,
- "This constructor must be noexcept");
- static_assert(!test_convertible<file_status, file_type, perms>(),
- "This constructor must b explicit");
- const file_status f(file_type::regular, perms::owner_read);
- assert(f.type() == file_type::regular);
- assert(f.permissions() == perms::owner_read);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class file_status
-
-// void type(file_type) noexcept;
-// void permissions(perms) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-
-int main() {
- using namespace fs;
-
- file_status st;
-
- // type test
- {
- static_assert(noexcept(st.type(file_type::regular)),
- "operation must be noexcept");
- static_assert(std::is_same<decltype(st.type(file_type::regular)), void>::value,
- "operation must return void");
- assert(st.type() != file_type::regular);
- st.type(file_type::regular);
- assert(st.type() == file_type::regular);
- }
- // permissions test
- {
- static_assert(noexcept(st.permissions(perms::owner_read)),
- "operation must be noexcept");
- static_assert(std::is_same<decltype(st.permissions(perms::owner_read)), void>::value,
- "operation must return void");
- assert(st.permissions() != perms::owner_read);
- st.permissions(perms::owner_read);
- assert(st.permissions() == perms::owner_read);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class file_status
-
-// file_type type() const noexcept;
-// perms permissions(p) const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-
-int main() {
- using namespace fs;
-
- const file_status st(file_type::regular, perms::owner_read);
-
- // type test
- {
- static_assert(noexcept(st.type()),
- "operation must be noexcept");
- static_assert(std::is_same<decltype(st.type()), file_type>::value,
- "operation must return file_type");
- assert(st.type() == file_type::regular);
- }
- // permissions test
- {
- static_assert(noexcept(st.permissions()),
- "operation must be noexcept");
- static_assert(std::is_same<decltype(st.permissions()), perms>::value,
- "operation must return perms");
- assert(st.permissions() == perms::owner_read);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class filesystem_error
-
-// filesystem_error(const string& what_arg, error_code ec);
-// filesystem_error(const string& what_arg, const path& p1, error_code ec);
-// filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec);
-// const std::error_code& code() const;
-// const char* what() const noexcept;
-// const path& path1() const noexcept;
-// const path& path2() const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-void test_constructors() {
- using namespace fs;
-
- // The string returned by "filesystem_error::what() must contain runtime_error::what()
- const std::string what_arg = "Hello World";
- const std::string what_contains = std::runtime_error(what_arg).what();
- assert(what_contains.find(what_arg) != std::string::npos);
- auto CheckWhat = [what_contains](filesystem_error const& e) {
- std::string s = e.what();
- assert(s.find(what_contains) != std::string::npos);
- };
-
- std::error_code ec = std::make_error_code(std::errc::file_exists);
- const path p1("foo");
- const path p2("bar");
-
- // filesystem_error(const string& what_arg, error_code ec);
- {
- ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, ec));
- filesystem_error e(what_arg, ec);
- CheckWhat(e);
- assert(e.code() == ec);
- assert(e.path1().empty() && e.path2().empty());
- }
- // filesystem_error(const string& what_arg, const path&, error_code ec);
- {
- ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, ec));
- filesystem_error e(what_arg, p1, ec);
- CheckWhat(e);
- assert(e.code() == ec);
- assert(e.path1() == p1);
- assert(e.path2().empty());
- }
- // filesystem_error(const string& what_arg, const path&, const path&, error_code ec);
- {
- ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, p2, ec));
- filesystem_error e(what_arg, p1, p2, ec);
- CheckWhat(e);
- assert(e.code() == ec);
- assert(e.path1() == p1);
- assert(e.path2() == p2);
- }
-}
-
-void test_signatures()
-{
- using namespace fs;
- const path p;
- std::error_code ec;
- const filesystem_error e("lala", ec);
- // const path& path1() const noexcept;
- {
- ASSERT_SAME_TYPE(path const&, decltype(e.path1()));
- ASSERT_NOEXCEPT(e.path1());
- }
- // const path& path2() const noexcept
- {
- ASSERT_SAME_TYPE(path const&, decltype(e.path2()));
- ASSERT_NOEXCEPT(e.path2());
- }
- // const char* what() const noexcept
- {
- ASSERT_SAME_TYPE(const char*, decltype(e.what()));
- ASSERT_NOEXCEPT(e.what());
- }
-}
-
-int main() {
- static_assert(std::is_base_of<std::system_error, fs::filesystem_error>::value, "");
- test_constructors();
- test_signatures();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class Source>
-// path(const Source& source);
-// template <class InputIterator>
-// path(InputIterator first, InputIterator last);
-
-
-#include "filesystem_include.hpp"
-#include <iterator>
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "filesystem_test_helper.hpp"
-
-
-
-template <class It>
-std::reverse_iterator<It> mkRev(It it) {
- return std::reverse_iterator<It>(it);
-}
-
-void checkIteratorConcepts() {
- using namespace fs;
- using It = path::iterator;
- using Traits = std::iterator_traits<It>;
- ASSERT_SAME_TYPE(Traits::iterator_category, std::bidirectional_iterator_tag);
- ASSERT_SAME_TYPE(Traits::value_type, path);
- ASSERT_SAME_TYPE(Traits::pointer, path const*);
- ASSERT_SAME_TYPE(Traits::reference, path const&);
- {
- It it;
- ASSERT_SAME_TYPE(It&, decltype(++it));
- ASSERT_SAME_TYPE(It, decltype(it++));
- ASSERT_SAME_TYPE(It&, decltype(--it));
- ASSERT_SAME_TYPE(It, decltype(it--));
- ASSERT_SAME_TYPE(Traits::reference, decltype(*it));
- ASSERT_SAME_TYPE(Traits::pointer, decltype(it.operator->()));
- ASSERT_SAME_TYPE(std::string const&, decltype(it->native()));
- ASSERT_SAME_TYPE(bool, decltype(it == it));
- ASSERT_SAME_TYPE(bool, decltype(it != it));
- }
- {
- path const p;
- ASSERT_SAME_TYPE(It, decltype(p.begin()));
- ASSERT_SAME_TYPE(It, decltype(p.end()));
- assert(p.begin() == p.end());
- }
-}
-
-void checkBeginEndBasic() {
- using namespace fs;
- using It = path::iterator;
- {
- path const p;
- ASSERT_SAME_TYPE(It, decltype(p.begin()));
- ASSERT_SAME_TYPE(It, decltype(p.end()));
- assert(p.begin() == p.end());
- }
- {
- path const p("foo");
- It default_constructed;
- default_constructed = p.begin();
- assert(default_constructed == p.begin());
- assert(default_constructed != p.end());
- default_constructed = p.end();
- assert(default_constructed == p.end());
- assert(default_constructed != p.begin());
- }
- {
- path p("//root_name//first_dir////second_dir");
- const path expect[] = {"/", "root_name", "first_dir", "second_dir"};
- assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect)));
- assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect)));
-
- }
- {
- path p("////foo/bar/baz///");
- const path expect[] = {"/", "foo", "bar", "baz", ""};
- assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect)));
- assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect)));
-
- }
-
-}
-
-int main() {
- using namespace fs;
- checkIteratorConcepts();
- checkBeginEndBasic(); // See path.decompose.pass.cpp for more tests.
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& operator/=(path const&)
-// template <class Source>
-// path& operator/=(Source const&);
-// template <class Source>
-// path& append(Source const&);
-// template <class InputIterator>
-// path& append(InputIterator first, InputIterator last);
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <string_view>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-#include "verbose_assert.h"
-
-
-struct AppendOperatorTestcase {
- MultiStringType lhs;
- MultiStringType rhs;
- MultiStringType expect;
-};
-
-#define S(Str) MKSTR(Str)
-const AppendOperatorTestcase Cases[] =
- {
- {S(""), S(""), S("")}
- , {S("p1"), S("p2"), S("p1/p2")}
- , {S("p1/"), S("p2"), S("p1/p2")}
- , {S("p1"), S("/p2"), S("/p2")}
- , {S("p1/"), S("/p2"), S("/p2")}
- , {S("p1"), S("\\p2"), S("p1/\\p2")}
- , {S("p1\\"), S("p2"), S("p1\\/p2")}
- , {S("p1\\"), S("\\p2"), S("p1\\/\\p2")}
- , {S(""), S("p2"), S("p2")}
- , {S("/p1"), S("p2"), S("/p1/p2")}
- , {S("/p1"), S("/p2"), S("/p2")}
- , {S("/p1/p3"), S("p2"), S("/p1/p3/p2")}
- , {S("/p1/p3/"), S("p2"), S("/p1/p3/p2")}
- , {S("/p1/"), S("p2"), S("/p1/p2")}
- , {S("/p1/p3/"), S("/p2/p4"), S("/p2/p4")}
- , {S("/"), S(""), S("/")}
- , {S("/p1"), S("/p2/"), S("/p2/")}
- , {S("p1"), S(""), S("p1/")}
- , {S("p1/"), S(""), S("p1/")}
- };
-
-
-const AppendOperatorTestcase LongLHSCases[] =
- {
- {S("p1"), S("p2"), S("p1/p2")}
- , {S("p1/"), S("p2"), S("p1/p2")}
- , {S("p1"), S("/p2"), S("/p2")}
- , {S("/p1"), S("p2"), S("/p1/p2")}
- };
-#undef S
-
-
-// The append operator may need to allocate a temporary buffer before a code_cvt
-// conversion. Test if this allocation occurs by:
-// 1. Create a path, `LHS`, and reserve enough space to append `RHS`.
-// This prevents `LHS` from allocating during the actual appending.
-// 2. Create a `Source` object `RHS`, which represents a "large" string.
-// (The string must not trigger the SSO)
-// 3. Append `RHS` to `LHS` and check for the expected allocation behavior.
-template <class CharT>
-void doAppendSourceAllocTest(AppendOperatorTestcase const& TC)
-{
- using namespace fs;
- using Ptr = CharT const*;
- using Str = std::basic_string<CharT>;
- using StrView = std::basic_string_view<CharT>;
- using InputIter = input_iterator<Ptr>;
-
- const Ptr L = TC.lhs;
- Str RShort = (Ptr)TC.rhs;
- Str EShort = (Ptr)TC.expect;
- assert(RShort.size() >= 2);
- CharT c = RShort.back();
- RShort.append(100, c);
- EShort.append(100, c);
- const Ptr R = RShort.data();
- const Str& E = EShort;
- std::size_t ReserveSize = E.size() + 3;
- // basic_string
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- Str RHS(R);
- {
- DisableAllocationGuard g;
- LHS /= RHS;
- }
- ASSERT_PRED(PathEq, LHS , E);
- }
- // basic_string_view
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- StrView RHS(R);
- {
- DisableAllocationGuard g;
- LHS /= RHS;
- }
- assert(PathEq(LHS, E));
- }
- // CharT*
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- Ptr RHS(R);
- {
- DisableAllocationGuard g;
- LHS /= RHS;
- }
- assert(PathEq(LHS, E));
- }
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- Ptr RHS(R);
- {
- DisableAllocationGuard g;
- LHS.append(RHS, StrEnd(RHS));
- }
- assert(PathEq(LHS, E));
- }
- // input iterator - For non-native char types, appends needs to copy the
- // iterator range into a contiguous block of memory before it can perform the
- // code_cvt conversions.
- // For "char" no allocations will be performed because no conversion is
- // required.
- bool DisableAllocations = std::is_same<CharT, char>::value;
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- InputIter RHS(R);
- {
- RequireAllocationGuard g; // requires 1 or more allocations occur by default
- if (DisableAllocations) g.requireExactly(0);
- LHS /= RHS;
- }
- assert(PathEq(LHS, E));
- }
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- InputIter RHS(R);
- InputIter REnd(StrEnd(R));
- {
- RequireAllocationGuard g;
- if (DisableAllocations) g.requireExactly(0);
- LHS.append(RHS, REnd);
- }
- assert(PathEq(LHS, E));
- }
-}
-
-template <class CharT>
-void doAppendSourceTest(AppendOperatorTestcase const& TC)
-{
- using namespace fs;
- using Ptr = CharT const*;
- using Str = std::basic_string<CharT>;
- using StrView = std::basic_string_view<CharT>;
- using InputIter = input_iterator<Ptr>;
- const Ptr L = TC.lhs;
- const Ptr R = TC.rhs;
- const Ptr E = TC.expect;
- // basic_string
- {
- path Result(L);
- Str RHS(R);
- path& Ref = (Result /= RHS);
- ASSERT_EQ(Result, E)
- << DISPLAY(L) << DISPLAY(R);
- assert(&Ref == &Result);
- }
- {
- path LHS(L);
- Str RHS(R);
- path& Ref = LHS.append(RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- // basic_string_view
- {
- path LHS(L);
- StrView RHS(R);
- path& Ref = (LHS /= RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- StrView RHS(R);
- path& Ref = LHS.append(RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- // Char*
- {
- path LHS(L);
- Str RHS(R);
- path& Ref = (LHS /= RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- Ptr RHS(R);
- path& Ref = LHS.append(RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- Ptr RHS(R);
- path& Ref = LHS.append(RHS, StrEnd(RHS));
- ASSERT_PRED(PathEq, LHS, E)
- << DISPLAY(L) << DISPLAY(R);
- assert(&Ref == &LHS);
- }
- // iterators
- {
- path LHS(L);
- InputIter RHS(R);
- path& Ref = (LHS /= RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- {
- path LHS(L); InputIter RHS(R);
- path& Ref = LHS.append(RHS);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- InputIter RHS(R);
- InputIter REnd(StrEnd(R));
- path& Ref = LHS.append(RHS, REnd);
- assert(PathEq(LHS, E));
- assert(&Ref == &LHS);
- }
-}
-
-
-
-template <class It, class = decltype(fs::path{}.append(std::declval<It>()))>
-constexpr bool has_append(int) { return true; }
-template <class It>
-constexpr bool has_append(long) { return false; }
-
-template <class It, class = decltype(fs::path{}.operator/=(std::declval<It>()))>
-constexpr bool has_append_op(int) { return true; }
-template <class It>
-constexpr bool has_append_op(long) { return false; }
-
-template <class It>
-constexpr bool has_append() {
- static_assert(has_append<It>(0) == has_append_op<It>(0), "must be same");
- return has_append<It>(0) && has_append_op<It>(0);
-}
-
-void test_sfinae()
-{
- using namespace fs;
- {
- using It = const char* const;
- static_assert(has_append<It>(), "");
- }
- {
- using It = input_iterator<const char*>;
- static_assert(has_append<It>(), "");
- }
- {
- struct Traits {
- using iterator_category = std::input_iterator_tag;
- using value_type = const char;
- using pointer = const char*;
- using reference = const char&;
- using difference_type = std::ptrdiff_t;
- };
- using It = input_iterator<const char*, Traits>;
- static_assert(has_append<It>(), "");
- }
- {
- using It = output_iterator<const char*>;
- static_assert(!has_append<It>(), "");
-
- }
- {
- static_assert(!has_append<int*>(), "");
- }
- {
- static_assert(!has_append<char>(), "");
- static_assert(!has_append<const char>(), "");
- }
-}
-
-int main()
-{
- using namespace fs;
- for (auto const & TC : Cases) {
- {
- const char* LHS_In = TC.lhs;
- const char* RHS_In = TC.rhs;
- path LHS(LHS_In);
- path RHS(RHS_In);
- path& Res = (LHS /= RHS);
- ASSERT_PRED(PathEq, Res, (const char*)TC.expect)
- << DISPLAY(LHS_In) << DISPLAY(RHS_In);
- assert(&Res == &LHS);
- }
- doAppendSourceTest<char> (TC);
- doAppendSourceTest<wchar_t> (TC);
- doAppendSourceTest<char16_t>(TC);
- doAppendSourceTest<char32_t>(TC);
- }
- for (auto const & TC : LongLHSCases) {
- doAppendSourceAllocTest<char>(TC);
- doAppendSourceAllocTest<wchar_t>(TC);
- }
- test_sfinae();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& operator=(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "count_new.hpp"
-
-
-int main() {
- using namespace fs;
- path p("abc");
- p = {};
- assert(p.native() == "");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& operator=(path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-int main() {
- using namespace fs;
- static_assert(std::is_copy_assignable<path>::value, "");
- static_assert(!std::is_nothrow_copy_assignable<path>::value, "should not be noexcept");
- const std::string s("foo");
- const path p(s);
- path p2;
- path& pref = (p2 = p);
- assert(p.native() == s);
- assert(p2.native() == s);
- assert(&pref == &p2);
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& operator=(path&&) noexcept
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "count_new.hpp"
-
-
-int main() {
- using namespace fs;
- static_assert(std::is_nothrow_move_assignable<path>::value, "");
- assert(globalMemCounter.checkOutstandingNewEq(0));
- const std::string s("we really really really really really really really "
- "really really long string so that we allocate");
- assert(globalMemCounter.checkOutstandingNewEq(1));
- path p(s);
- {
- DisableAllocationGuard g;
- path p2;
- path& pref = (p2 = std::move(p));
- assert(p2.native() == s);
- assert(p.native() != s); // Testing moved from state
- assert(&pref == &p2);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class Source>
-// path& operator=(Source const&);
-// path& operator=(string_type&&);
-// template <class Source>
-// path& assign(Source const&);
-// template <class InputIterator>
-// path& assign(InputIterator first, InputIterator last);
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <string_view>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-#include <iostream>
-
-
-template <class CharT>
-void RunTestCase(MultiStringType const& MS) {
- using namespace fs;
- const char* Expect = MS;
- const CharT* TestPath = MS;
- const CharT* TestPathEnd = StrEnd(TestPath);
- const std::size_t Size = TestPathEnd - TestPath;
- const std::size_t SSize = StrEnd(Expect) - Expect;
- assert(Size == SSize);
- //////////////////////////////////////////////////////////////////////////////
- // basic_string<Char, Traits, Alloc>
- {
- const std::basic_string<CharT> S(TestPath);
- path p; PathReserve(p, S.length() + 1);
- {
- // string provides a contiguous iterator. No allocation needed.
- DisableAllocationGuard g;
- path& pref = (p = S);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- assert(p.string<CharT>() == S);
- }
- {
- const std::basic_string<CharT> S(TestPath);
- path p; PathReserve(p, S.length() + 1);
- {
- DisableAllocationGuard g;
- path& pref = p.assign(S);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- assert(p.string<CharT>() == S);
- }
- // basic_string<Char, Traits, Alloc>
- {
- const std::basic_string_view<CharT> S(TestPath);
- path p; PathReserve(p, S.length() + 1);
- {
- // string provides a contiguous iterator. No allocation needed.
- DisableAllocationGuard g;
- path& pref = (p = S);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- assert(p.string<CharT>() == S);
- }
- {
- const std::basic_string_view<CharT> S(TestPath);
- path p; PathReserve(p, S.length() + 1);
- {
- DisableAllocationGuard g;
- path& pref = p.assign(S);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- assert(p.string<CharT>() == S);
- }
- //////////////////////////////////////////////////////////////////////////////
- // Char* pointers
- {
- path p; PathReserve(p, Size + 1);
- {
- // char* pointers are contiguous and can be used with code_cvt directly.
- // no allocations needed.
- DisableAllocationGuard g;
- path& pref = (p = TestPath);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- {
- path p; PathReserve(p, Size + 1);
- {
- DisableAllocationGuard g;
- path& pref = p.assign(TestPath);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- {
- path p; PathReserve(p, Size + 1);
- {
- DisableAllocationGuard g;
- path& pref = p.assign(TestPath, TestPathEnd);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- //////////////////////////////////////////////////////////////////////////////
- // Iterators
- {
- using It = input_iterator<const CharT*>;
- path p; PathReserve(p, Size + 1);
- It it(TestPath);
- {
- // Iterators cannot be used with code_cvt directly. This assignment
- // may allocate if it's larger than a "short-string".
- path& pref = (p = it);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- {
- using It = input_iterator<const CharT*>;
- path p; PathReserve(p, Size + 1);
- It it(TestPath);
- {
- path& pref = p.assign(it);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- {
- using It = input_iterator<const CharT*>;
- path p; PathReserve(p, Size + 1);
- It it(TestPath);
- It e(TestPathEnd);
- {
- path& pref = p.assign(it, e);
- assert(&pref == &p);
- }
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
-}
-
-template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>
-constexpr bool has_assign(int) { return true; }
-template <class It>
-constexpr bool has_assign(long) { return false; }
-template <class It>
-constexpr bool has_assign() { return has_assign<It>(0); }
-
-void test_sfinae() {
- using namespace fs;
- {
- using It = const char* const;
- static_assert(std::is_assignable<path, It>::value, "");
- static_assert(has_assign<It>(), "");
- }
- {
- using It = input_iterator<const char*>;
- static_assert(std::is_assignable<path, It>::value, "");
- static_assert(has_assign<It>(), "");
- }
- {
- struct Traits {
- using iterator_category = std::input_iterator_tag;
- using value_type = const char;
- using pointer = const char*;
- using reference = const char&;
- using difference_type = std::ptrdiff_t;
- };
- using It = input_iterator<const char*, Traits>;
- static_assert(std::is_assignable<path, It>::value, "");
- static_assert(has_assign<It>(), "");
- }
- {
- using It = output_iterator<const char*>;
- static_assert(!std::is_assignable<path, It>::value, "");
- static_assert(!has_assign<It>(), "");
-
- }
- {
- static_assert(!std::is_assignable<path, int*>::value, "");
- static_assert(!has_assign<int*>(), "");
- }
-}
-
-void RunStringMoveTest(const char* Expect) {
- using namespace fs;
- std::string ss(Expect);
- path p;
- {
- DisableAllocationGuard g; ((void)g);
- path& pr = (p = std::move(ss));
- assert(&pr == &p);
- }
- assert(p == Expect);
- {
- // Signature test
- ASSERT_NOEXCEPT(p = std::move(ss));
- }
-}
-
-int main() {
- for (auto const& MS : PathList) {
- RunTestCase<char>(MS);
- RunTestCase<wchar_t>(MS);
- RunTestCase<char16_t>(MS);
- RunTestCase<char32_t>(MS);
- RunStringMoveTest(MS);
- }
- test_sfinae();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// int compare(path const&) const noexcept;
-// int compare(string_type const&) const;
-// int compare(value_type const*) const;
-//
-// bool operator==(path const&, path const&) noexcept;
-// bool operator!=(path const&, path const&) noexcept;
-// bool operator< (path const&, path const&) noexcept;
-// bool operator<=(path const&, path const&) noexcept;
-// bool operator> (path const&, path const&) noexcept;
-// bool operator>=(path const&, path const&) noexcept;
-//
-// size_t hash_value(path const&) noexcept;
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-#include "verbose_assert.h"
-
-struct PathCompareTest {
- const char* LHS;
- const char* RHS;
- int expect;
-};
-
-#define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
-#define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
-#define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
-#define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
-const PathCompareTest CompareTestCases[] =
-{
- {"", "", 0},
- {"a", "", 1},
- {"", "a", -1},
- {"a/b/c", "a/b/c", 0},
- {"b/a/c", "a/b/c", 1},
- {"a/b/c", "b/a/c", -1},
- {"a/b", "a/b/c", -1},
- {"a/b/c", "a/b", 1},
- {"a/b/", "a/b/.", -1},
- {"a/b/", "a/b", 1},
- {"a/b//////", "a/b/////.", -1},
- {"a/.././b", "a///..//.////b", 0},
- {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators
- {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory
- {"/foo/bar/", "/foo/bar", 1}, // trailing separator
- {"//" LONGA "////" LONGB "/" LONGC "///" LONGD, "//" LONGA "/" LONGB "/" LONGC "/" LONGD, 0},
- { LONGA "/" LONGB "/" LONGC, LONGA "/" LONGB "/" LONGB, 1}
-
-};
-#undef LONGA
-#undef LONGB
-#undef LONGC
-#undef LONGD
-
-static inline int normalize_ret(int ret)
-{
- return ret < 0 ? -1 : (ret > 0 ? 1 : 0);
-}
-
-int main()
-{
- using namespace fs;
- for (auto const & TC : CompareTestCases) {
- const path p1(TC.LHS);
- const path p2(TC.RHS);
- const std::string R(TC.RHS);
- const std::string_view RV(TC.RHS);
- const int E = TC.expect;
- { // compare(...) functions
- DisableAllocationGuard g; // none of these operations should allocate
-
- // check runtime results
- int ret1 = normalize_ret(p1.compare(p2));
- int ret2 = normalize_ret(p1.compare(R));
- int ret3 = normalize_ret(p1.compare(TC.RHS));
- int ret4 = normalize_ret(p1.compare(RV));
-
- g.release();
- ASSERT_EQ(ret1, ret2);
- ASSERT_EQ(ret1, ret3);
- ASSERT_EQ(ret1, ret4);
- ASSERT_EQ(ret1, E)
- << DISPLAY(TC.LHS) << DISPLAY(TC.RHS);
-
- // check signatures
- ASSERT_NOEXCEPT(p1.compare(p2));
- }
- { // comparison operators
- DisableAllocationGuard g; // none of these operations should allocate
-
- // Check runtime result
- assert((p1 == p2) == (E == 0));
- assert((p1 != p2) == (E != 0));
- assert((p1 < p2) == (E < 0));
- assert((p1 <= p2) == (E <= 0));
- assert((p1 > p2) == (E > 0));
- assert((p1 >= p2) == (E >= 0));
-
- // Check signatures
- ASSERT_NOEXCEPT(p1 == p2);
- ASSERT_NOEXCEPT(p1 != p2);
- ASSERT_NOEXCEPT(p1 < p2);
- ASSERT_NOEXCEPT(p1 <= p2);
- ASSERT_NOEXCEPT(p1 > p2);
- ASSERT_NOEXCEPT(p1 >= p2);
- }
- { // check hash values
- auto h1 = hash_value(p1);
- auto h2 = hash_value(p2);
- assert((h1 == h2) == (p1 == p2));
- // check signature
- ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1)));
- ASSERT_NOEXCEPT(hash_value(p1));
- }
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& operator+=(const path& x);
-// path& operator+=(const string_type& x);
-// path& operator+=(string_view x);
-// path& operator+=(const value_type* x);
-// path& operator+=(value_type x);
-// template <class Source>
-// path& operator+=(const Source& x);
-// template <class EcharT>
-// path& operator+=(EcharT x);
-// template <class Source>
-// path& concat(const Source& x);
-// template <class InputIterator>
-// path& concat(InputIterator first, InputIterator last);
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <string>
-#include <string_view>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-struct ConcatOperatorTestcase {
- MultiStringType lhs;
- MultiStringType rhs;
- MultiStringType expect;
-};
-
-#define LONGSTR "LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR"
-#define S(Str) MKSTR(Str)
-const ConcatOperatorTestcase Cases[] =
- {
- {S(""), S(""), S("")}
- , {S("p1"), S("p2"), S("p1p2")}
- , {S("p1/"), S("/p2"), S("p1//p2")}
- , {S(""), S("\\foo/bar/baz"), S("\\foo/bar/baz")}
- , {S("c:\\foo"), S(""), S("c:\\foo")}
- , {S(LONGSTR), S("foo"), S(LONGSTR "foo")}
- , {S("abcdefghijklmnopqrstuvwxyz/\\"), S("/\\123456789"), S("abcdefghijklmnopqrstuvwxyz/\\/\\123456789")}
- };
-const ConcatOperatorTestcase LongLHSCases[] =
- {
- {S(""), S(LONGSTR), S(LONGSTR)}
- , {S("p1/"), S(LONGSTR), S("p1/" LONGSTR)}
- };
-const ConcatOperatorTestcase CharTestCases[] =
- {
- {S(""), S("P"), S("P")}
- , {S("/fooba"), S("r"), S("/foobar")}
- };
-#undef S
-#undef LONGSTR
-
-// The concat operator may need to allocate a temporary buffer before a code_cvt
-// conversion. Test if this allocation occurs by:
-// 1. Create a path, `LHS`, and reserve enough space to append `RHS`.
-// This prevents `LHS` from allocating during the actual appending.
-// 2. Create a `Source` object `RHS`, which represents a "large" string.
-// (The string must not trigger the SSO)
-// 3. Concat `RHS` to `LHS` and check for the expected allocation behavior.
-template <class CharT>
-void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC)
-{
- using namespace fs;
- using Ptr = CharT const*;
- using Str = std::basic_string<CharT>;
- using StrView = std::basic_string_view<CharT>;
- using InputIter = input_iterator<Ptr>;
-
- const Ptr L = TC.lhs;
- const Ptr R = TC.rhs;
- const Ptr E = TC.expect;
- std::size_t ReserveSize = StrLen(E) + 1;
- // basic_string
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- Str RHS(R);
- {
- DisableAllocationGuard g;
- LHS += RHS;
- }
- assert(LHS == E);
- }
- // basic_string_view
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- StrView RHS(R);
- {
- DisableAllocationGuard g;
- LHS += RHS;
- }
- assert(LHS == E);
- }
- // CharT*
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- Ptr RHS(R);
- {
- DisableAllocationGuard g;
- LHS += RHS;
- }
- assert(LHS == E);
- }
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- Ptr RHS(R);
- {
- DisableAllocationGuard g;
- LHS.concat(RHS, StrEnd(RHS));
- }
- assert(LHS == E);
- }
- // input iterator - For non-native char types, appends needs to copy the
- // iterator range into a contiguous block of memory before it can perform the
- // code_cvt conversions.
- // For "char" no allocations will be performed because no conversion is
- // required.
- bool DisableAllocations = std::is_same<CharT, char>::value;
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- InputIter RHS(R);
- {
- RequireAllocationGuard g; // requires 1 or more allocations occur by default
- if (DisableAllocations) g.requireExactly(0);
- LHS += RHS;
- }
- assert(LHS == E);
- }
- {
- path LHS(L); PathReserve(LHS, ReserveSize);
- InputIter RHS(R);
- InputIter REnd(StrEnd(R));
- {
- RequireAllocationGuard g;
- if (DisableAllocations) g.requireExactly(0);
- LHS.concat(RHS, REnd);
- }
- assert(LHS == E);
- }
-}
-
-template <class CharT>
-void doConcatSourceTest(ConcatOperatorTestcase const& TC)
-{
- using namespace fs;
- using Ptr = CharT const*;
- using Str = std::basic_string<CharT>;
- using StrView = std::basic_string_view<CharT>;
- using InputIter = input_iterator<Ptr>;
- const Ptr L = TC.lhs;
- const Ptr R = TC.rhs;
- const Ptr E = TC.expect;
- // basic_string
- {
- path LHS(L);
- Str RHS(R);
- path& Ref = (LHS += RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- Str RHS(R);
- path& Ref = LHS.concat(RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- // basic_string_view
- {
- path LHS(L);
- StrView RHS(R);
- path& Ref = (LHS += RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- StrView RHS(R);
- path& Ref = LHS.concat(RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- // Char*
- {
- path LHS(L);
- Str RHS(R);
- path& Ref = (LHS += RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- Ptr RHS(R);
- path& Ref = LHS.concat(RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- Ptr RHS(R);
- path& Ref = LHS.concat(RHS, StrEnd(RHS));
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- // iterators
- {
- path LHS(L);
- InputIter RHS(R);
- path& Ref = (LHS += RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- {
- path LHS(L); InputIter RHS(R);
- path& Ref = LHS.concat(RHS);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
- {
- path LHS(L);
- InputIter RHS(R);
- InputIter REnd(StrEnd(R));
- path& Ref = LHS.concat(RHS, REnd);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
-}
-
-template <class CharT>
-void doConcatECharTest(ConcatOperatorTestcase const& TC)
-{
- using namespace fs;
- using Ptr = CharT const*;
- const Ptr RStr = TC.rhs;
- assert(StrLen(RStr) == 1);
- const Ptr L = TC.lhs;
- const CharT R = RStr[0];
- const Ptr E = TC.expect;
- {
- path LHS(L);
- path& Ref = (LHS += R);
- assert(LHS == E);
- assert(&Ref == &LHS);
- }
-}
-
-
-template <class It, class = decltype(fs::path{}.concat(std::declval<It>()))>
-constexpr bool has_concat(int) { return true; }
-template <class It>
-constexpr bool has_concat(long) { return false; }
-
-template <class It, class = decltype(fs::path{}.operator+=(std::declval<It>()))>
-constexpr bool has_concat_op(int) { return true; }
-template <class It>
-constexpr bool has_concat_op(long) { return false; }
-template <class It>
-constexpr bool has_concat_op() { return has_concat_op<It>(0); }
-
-template <class It>
-constexpr bool has_concat() {
- static_assert(has_concat<It>(0) == has_concat_op<It>(0), "must be same");
- return has_concat<It>(0) && has_concat_op<It>(0);
-}
-
-void test_sfinae() {
- using namespace fs;
- {
- static_assert(has_concat_op<char>(), "");
- static_assert(has_concat_op<const char>(), "");
- static_assert(has_concat_op<char16_t>(), "");
- static_assert(has_concat_op<const char16_t>(), "");
- }
- {
- using It = const char* const;
- static_assert(has_concat<It>(), "");
- }
- {
- using It = input_iterator<const char*>;
- static_assert(has_concat<It>(), "");
- }
- {
- struct Traits {
- using iterator_category = std::input_iterator_tag;
- using value_type = const char;
- using pointer = const char*;
- using reference = const char&;
- using difference_type = std::ptrdiff_t;
- };
- using It = input_iterator<const char*, Traits>;
- static_assert(has_concat<It>(), "");
- }
- {
- using It = output_iterator<const char*>;
- static_assert(!has_concat<It>(), "");
- }
- {
- static_assert(!has_concat<int>(0), "");
- // operator+=(int) is well formed since it converts to operator+=(value_type)
- // but concat(int) isn't valid because there is no concat(value_type).
- // This should probably be addressed by a LWG issue.
- static_assert(has_concat_op<int>(), "");
- }
- {
- static_assert(!has_concat<int*>(), "");
- }
-}
-
-int main()
-{
- using namespace fs;
- for (auto const & TC : Cases) {
- {
- path LHS((const char*)TC.lhs);
- path RHS((const char*)TC.rhs);
- path& Ref = (LHS += RHS);
- assert(LHS == (const char*)TC.expect);
- assert(&Ref == &LHS);
- }
- {
- path LHS((const char*)TC.lhs);
- std::string_view RHS((const char*)TC.rhs);
- path& Ref = (LHS += RHS);
- assert(LHS == (const char*)TC.expect);
- assert(&Ref == &LHS);
- }
- doConcatSourceTest<char> (TC);
- doConcatSourceTest<wchar_t> (TC);
- doConcatSourceTest<char16_t>(TC);
- doConcatSourceTest<char32_t>(TC);
- }
- for (auto const & TC : LongLHSCases) {
- // Do path test
- {
- path LHS((const char*)TC.lhs);
- path RHS((const char*)TC.rhs);
- const char* E = TC.expect;
- PathReserve(LHS, StrLen(E) + 5);
- {
- DisableAllocationGuard g;
- path& Ref = (LHS += RHS);
- assert(&Ref == &LHS);
- }
- assert(LHS == E);
- }
- {
- path LHS((const char*)TC.lhs);
- std::string_view RHS((const char*)TC.rhs);
- const char* E = TC.expect;
- PathReserve(LHS, StrLen(E) + 5);
- {
- DisableAllocationGuard g;
- path& Ref = (LHS += RHS);
- assert(&Ref == &LHS);
- }
- assert(LHS == E);
- }
- doConcatSourceAllocTest<char>(TC);
- doConcatSourceAllocTest<wchar_t>(TC);
- }
- for (auto const& TC : CharTestCases) {
- doConcatECharTest<char>(TC);
- doConcatECharTest<wchar_t>(TC);
- doConcatECharTest<char16_t>(TC);
- doConcatECharTest<char32_t>(TC);
- }
- test_sfinae();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path(path const&)
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-int main() {
- using namespace fs;
- static_assert(std::is_copy_constructible<path>::value, "");
- static_assert(!std::is_nothrow_copy_constructible<path>::value, "should not be noexcept");
- const std::string s("foo");
- const path p(s);
- path p2(p);
- assert(p.native() == s);
- assert(p2.native() == s);
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path() noexcept
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-int main() {
- using namespace fs;
- static_assert(std::is_nothrow_default_constructible<path>::value, "");
- const path p;
- assert(p.empty());
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path(path&&) noexcept
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "count_new.hpp"
-
-
-int main() {
- using namespace fs;
- static_assert(std::is_nothrow_move_constructible<path>::value, "");
- assert(globalMemCounter.checkOutstandingNewEq(0));
- const std::string s("we really really really really really really really "
- "really really long string so that we allocate");
- assert(globalMemCounter.checkOutstandingNewEq(1));
- path p(s);
- {
- DisableAllocationGuard g;
- path p2(std::move(p));
- assert(p2.native() == s);
- assert(p.native() != s); // Testing moved from state
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class Source>
-// path(const Source& source);
-// template <class InputIterator>
-// path(InputIterator first, InputIterator last);
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "min_allocator.h"
-#include "filesystem_test_helper.hpp"
-
-
-template <class CharT, class ...Args>
-void RunTestCaseImpl(MultiStringType const& MS, Args... args) {
- using namespace fs;
- const char* Expect = MS;
- const CharT* TestPath = MS;
- const CharT* TestPathEnd = StrEnd(TestPath);
- const std::size_t Size = TestPathEnd - TestPath;
- const std::size_t SSize = StrEnd(Expect) - Expect;
- assert(Size == SSize);
- // StringTypes
- {
- const std::basic_string<CharT> S(TestPath);
- path p(S, args...);
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- assert(p.string<CharT>() == S);
- }
- {
- const std::basic_string_view<CharT> S(TestPath);
- path p(S, args...);
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- assert(p.string<CharT>() == S);
- }
- // Char* pointers
- {
- path p(TestPath, args...);
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- {
- path p(TestPath, TestPathEnd, args...);
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- // Iterators
- {
- using It = input_iterator<const CharT*>;
- path p(It{TestPath}, args...);
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
- {
- using It = input_iterator<const CharT*>;
- path p(It{TestPath}, It{TestPathEnd}, args...);
- assert(p.native() == Expect);
- assert(p.string<CharT>() == TestPath);
- }
-}
-
-template <class CharT, class ...Args>
-void RunTestCase(MultiStringType const& MS) {
- RunTestCaseImpl<CharT>(MS);
- RunTestCaseImpl<CharT>(MS, fs::path::format::auto_format);
- RunTestCaseImpl<CharT>(MS, fs::path::format::native_format);
- RunTestCaseImpl<CharT>(MS, fs::path::format::generic_format);
-}
-
-void test_sfinae() {
- using namespace fs;
- {
- using It = const char* const;
- static_assert(std::is_constructible<path, It>::value, "");
- }
- {
- using It = input_iterator<const char*>;
- static_assert(std::is_constructible<path, It>::value, "");
- }
- {
- struct Traits {
- using iterator_category = std::input_iterator_tag;
- using value_type = const char;
- using pointer = const char*;
- using reference = const char&;
- using difference_type = std::ptrdiff_t;
- };
- using It = input_iterator<const char*, Traits>;
- static_assert(std::is_constructible<path, It>::value, "");
- }
- {
- using It = output_iterator<const char*>;
- static_assert(!std::is_constructible<path, It>::value, "");
-
- }
- {
- static_assert(!std::is_constructible<path, int*>::value, "");
- }
-}
-
-int main() {
- for (auto const& MS : PathList) {
- RunTestCase<char>(MS);
- RunTestCase<wchar_t>(MS);
- RunTestCase<char16_t>(MS);
- RunTestCase<char32_t>(MS);
- }
- test_sfinae();
-}
+++ /dev/null
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// <experimental/filesystem>
-
-// class path
-
-// bool empty() const noexcept;
-
-// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
-// UNSUPPORTED: clang-3.3, clang-3.4, clang-3.5, clang-3.6, clang-3.7, clang-3.8
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-
-int main ()
-{
- fs::path c;
- c.empty(); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// 8.4.9 path decomposition [path.decompose]
-//------------------------------------------
-// path root_name() const;
-// path root_directory() const;
-// path root_path() const;
-// path relative_path() const;
-// path parent_path() const;
-// path filename() const;
-// path stem() const;
-// path extension() const;
-//-------------------------------
-// 8.4.10 path query [path.query]
-//-------------------------------
-// bool empty() const noexcept;
-// bool has_root_path() const;
-// bool has_root_name() const;
-// bool has_root_directory() const;
-// bool has_relative_path() const;
-// bool has_parent_path() const;
-// bool has_filename() const;
-// bool has_stem() const;
-// bool has_extension() const;
-// bool is_absolute() const;
-// bool is_relative() const;
-//-------------------------------
-// 8.5 path iterators [path.itr]
-//-------------------------------
-// iterator begin() const;
-// iterator end() const;
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-#include "assert_checkpoint.h"
-#include "verbose_assert.h"
-
-struct ComparePathExact {
- bool operator()(std::string const& LHS, std::string const& RHS) const {
- return LHS == RHS;
- }
-};
-
-struct PathDecomposeTestcase
-{
- std::string raw;
- std::vector<std::string> elements;
- std::string root_path;
- std::string root_name;
- std::string root_directory;
- std::string relative_path;
- std::string parent_path;
- std::string filename;
-};
-
-const PathDecomposeTestcase PathTestCases[] =
- {
- {"", {}, "", "", "", "", "", ""}
- , {".", {"."}, "", "", "", ".", "", "."}
- , {"..", {".."}, "", "", "", "..", "", ".."}
- , {"foo", {"foo"}, "", "", "", "foo", "", "foo"}
- , {"/", {"/"}, "/", "", "/", "", "/", ""}
- , {"/foo", {"/", "foo"}, "/", "", "/", "foo", "/", "foo"}
- , {"foo/", {"foo", ""}, "", "", "", "foo/", "foo", ""}
- , {"/foo/", {"/", "foo", ""}, "/", "", "/", "foo/", "/foo", ""}
- , {"foo/bar", {"foo","bar"}, "", "", "", "foo/bar", "foo", "bar"}
- , {"/foo//bar", {"/","foo","bar"}, "/", "", "/", "foo/bar", "/foo", "bar"}
- , {"//net", {"/", "net"}, "/", "", "/", "net", "/", "net"}
- , {"//net/foo", {"/", "net", "foo"}, "/", "", "/", "net/foo", "/net", "foo"}
- , {"///foo///", {"/", "foo", ""}, "/", "", "/", "foo///", "///foo", ""}
- , {"///foo///bar", {"/", "foo", "bar"}, "/", "", "/", "foo///bar", "///foo", "bar"}
- , {"/.", {"/", "."}, "/", "", "/", ".", "/", "."}
- , {"./", {".", ""}, "", "", "", "./", ".", ""}
- , {"/..", {"/", ".."}, "/", "", "/", "..", "/", ".."}
- , {"../", {"..", ""}, "", "", "", "../", "..", ""}
- , {"foo/.", {"foo", "."}, "", "", "", "foo/.", "foo", "."}
- , {"foo/..", {"foo", ".."}, "", "", "", "foo/..", "foo", ".."}
- , {"foo/./", {"foo", ".", ""}, "", "", "", "foo/./", "foo/.", ""}
- , {"foo/./bar", {"foo", ".", "bar"}, "", "", "", "foo/./bar", "foo/.", "bar"}
- , {"foo/../", {"foo", "..", ""}, "", "", "", "foo/../", "foo/..", ""}
- , {"foo/../bar", {"foo", "..", "bar"}, "", "", "", "foo/../bar", "foo/..", "bar"}
- , {"c:", {"c:"}, "", "", "", "c:", "", "c:"}
- , {"c:/", {"c:", ""}, "", "", "", "c:/", "c:", ""}
- , {"c:foo", {"c:foo"}, "", "", "", "c:foo", "", "c:foo"}
- , {"c:/foo", {"c:", "foo"}, "", "", "", "c:/foo", "c:", "foo"}
- , {"c:foo/", {"c:foo", ""}, "", "", "", "c:foo/", "c:foo", ""}
- , {"c:/foo/", {"c:", "foo", ""}, "", "", "", "c:/foo/", "c:/foo", ""}
- , {"c:/foo/bar", {"c:", "foo", "bar"}, "", "", "", "c:/foo/bar", "c:/foo", "bar"}
- , {"prn:", {"prn:"}, "", "", "", "prn:", "", "prn:"}
- , {"c:\\", {"c:\\"}, "", "", "", "c:\\", "", "c:\\"}
- , {"c:\\foo", {"c:\\foo"}, "", "", "", "c:\\foo", "", "c:\\foo"}
- , {"c:foo\\", {"c:foo\\"}, "", "", "", "c:foo\\", "", "c:foo\\"}
- , {"c:\\foo\\", {"c:\\foo\\"}, "", "", "", "c:\\foo\\", "", "c:\\foo\\"}
- , {"c:\\foo/", {"c:\\foo", ""}, "", "", "", "c:\\foo/", "c:\\foo", ""}
- , {"c:/foo\\bar", {"c:", "foo\\bar"}, "", "", "", "c:/foo\\bar", "c:", "foo\\bar"}
- , {"//", {"/"}, "/", "", "/", "", "/", ""}
- };
-
-void decompPathTest()
-{
- using namespace fs;
- for (auto const & TC : PathTestCases) {
- CHECKPOINT(TC.raw.c_str());
- fs::path p(TC.raw);
- ASSERT(p == TC.raw);
-
- ASSERT_EQ(p.root_path(), TC.root_path);
- ASSERT_NEQ(p.has_root_path(), TC.root_path.empty());
-
- ASSERT(p.root_name().native().empty())
- << DISPLAY(p.root_name());
- ASSERT_EQ(p.root_name(),TC.root_name);
- ASSERT_NEQ(p.has_root_name(), TC.root_name.empty());
-
- ASSERT_EQ(p.root_directory(), TC.root_directory);
- ASSERT_NEQ(p.has_root_directory(), TC.root_directory.empty());
-
- ASSERT_EQ(p.relative_path(), TC.relative_path);
- ASSERT_NEQ(p.has_relative_path(), TC.relative_path.empty());
-
- ASSERT_EQ(p.parent_path(), TC.parent_path);
- ASSERT_NEQ(p.has_parent_path(), TC.parent_path.empty());
-
- ASSERT_EQ(p.filename(), TC.filename);
- ASSERT_NEQ(p.has_filename(), TC.filename.empty());
-
- ASSERT_EQ(p.is_absolute(), p.has_root_directory());
- ASSERT_NEQ(p.is_relative(), p.is_absolute());
- if (p.empty())
- ASSERT(p.is_relative());
-
- ASSERT_COLLECTION_EQ_COMP(
- p.begin(), p.end(),
- TC.elements.begin(), TC.elements.end(),
- ComparePathExact()
- );
- // check backwards
-
- std::vector<fs::path> Parts;
- for (auto it = p.end(); it != p.begin(); )
- Parts.push_back(*--it);
- ASSERT_COLLECTION_EQ_COMP(Parts.begin(), Parts.end(),
- TC.elements.rbegin(), TC.elements.rend(),
- ComparePathExact());
- }
-}
-
-
-struct FilenameDecompTestcase
-{
- std::string raw;
- std::string filename;
- std::string stem;
- std::string extension;
-};
-
-const FilenameDecompTestcase FilenameTestCases[] =
-{
- {"", "", "", ""}
- , {".", ".", ".", ""}
- , {"..", "..", "..", ""}
- , {"/", "", "", ""}
- , {"foo", "foo", "foo", ""}
- , {"/foo/bar.txt", "bar.txt", "bar", ".txt"}
- , {"foo..txt", "foo..txt", "foo.", ".txt"}
- , {".profile", ".profile", ".profile", ""}
- , {".profile.txt", ".profile.txt", ".profile", ".txt"}
-};
-
-
-void decompFilenameTest()
-{
- using namespace fs;
- for (auto const & TC : FilenameTestCases) {
- CHECKPOINT(TC.raw.c_str());
- fs::path p(TC.raw);
- ASSERT_EQ(p, TC.raw);
- ASSERT_NOEXCEPT(p.empty());
-
- ASSERT_EQ(p.filename(), TC.filename);
- ASSERT_NEQ(p.has_filename(), TC.filename.empty());
-
- ASSERT_EQ(p.stem(), TC.stem);
- ASSERT_NEQ(p.has_stem(), TC.stem.empty());
-
- ASSERT_EQ(p.extension(), TC.extension);
- ASSERT_NEQ(p.has_extension(), TC.extension.empty());
- }
-}
-
-int main()
-{
- decompPathTest();
- decompFilenameTest();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path lexically_normal() const;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <iostream>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-int main() {
- // clang-format off
- struct {
- std::string input;
- std::string expect;
- } TestCases[] = {
- {"", ""},
- {"/a/b/c", "/a/b/c"},
- {"/a/b//c", "/a/b/c"},
- {"foo/./bar/..", "foo/"},
- {"foo/.///bar/../", "foo/"},
- {"/a/b/", "/a/b/"},
- {"a/b", "a/b"},
- {"a/b/.", "a/b/"},
- {"a/b/./", "a/b/"},
- {"a/..", "."},
- {".", "."},
- {"./", "."},
- {"./.", "."},
- {"./..", ".."},
- {"..", ".."},
- {"../..", "../.."},
- {"/../", "/"},
- {"/../..", "/"},
- {"/../../", "/"},
- {"..", ".."},
- {"../", ".."},
- {"/a/b/c/../", "/a/b/"},
- {"/a/b/./", "/a/b/"},
- {"/a/b/c/../d", "/a/b/d"},
- {"/a/b/c/../d/", "/a/b/d/"},
- {"//a/", "/a/"},
- {"//a/b/", "/a/b/"},
- {"//a/b/.", "/a/b/"},
- {"//a/..", "/"},
- ///===---------------------------------------------------------------===//
- /// Tests specifically for the clauses under [fs.path.generic]p6
- ///===---------------------------------------------------------------===//
- // p1: If the path is empty, stop.
- {"", ""},
- // p2: Replace each slash character in the root-name with a preferred
- // separator.
- {"NO_ROOT_NAME_ON_LINUX", "NO_ROOT_NAME_ON_LINUX"},
- // p3: Replace each directory-separator with a preferred-separator.
- // [ Note: The generic pathname grammar ([fs.path.generic]) defines
- // directory-separator as one or more slashes and preferred-separators.
- // — end note ]
- {"/", "/"},
- {"//", "/"},
- {"///", "/"},
- {"a/b", "a/b"},
- {"a//b", "a/b"},
- {"a///b", "a/b"},
- {"a/b/", "a/b/"},
- {"a/b//", "a/b/"},
- {"a/b///", "a/b/"},
- {"///a////b//////", "/a/b/"},
- // p4: Remove each dot filename and any immediately following directory
- // separators
- {"foo/.", "foo/"},
- {"foo/./bar/.", "foo/bar/"},
- {"./foo/././bar/./", "foo/bar/"},
- {".///foo//.////./bar/.///", "foo/bar/"},
- // p5: As long as any appear, remove a non-dot-dot filename immediately
- // followed by a directory-separator and a dot-dot filename, along with
- // any immediately following directory separator.
- {"foo/..", "."},
- {"foo/../", "."},
- {"foo/bar/..", "foo/"},
- {"foo/bar/../", "foo/"},
- {"foo/bar/../..", "."},
- {"foo/bar/../../", "."},
- {"foo/bar/baz/../..", "foo/"},
- {"foo/bar/baz/../../", "foo/"},
- {"foo/bar/./..", "foo/"},
- {"foo/bar/./../", "foo/"},
- // p6: If there is a root-directory, remove all dot-dot filenames and any
- // directory-separators immediately following them. [ Note: These dot-dot
- // filenames attempt to refer to nonexistent parent directories. — end note ]
- {"/..", "/"},
- {"/../", "/"},
- {"/foo/../..", "/"},
- {"/../foo", "/foo"},
- {"/../foo/../..", "/"},
- // p7: If the last filename is dot-dot, remove any trailing
- // directory-separator.
- {"../", ".."},
- {"../../", "../.."},
- {"foo/../bar/../..///", ".."},
- {"foo/../bar/..//..///../", "../.."},
- // p8: If the path is empty, add a dot
- {".", "."},
- {"./", "."},
- {"foo/..", "."}
- };
- // clang-format on
- int ID = 0;
- bool Failed = false;
- for (auto& TC : TestCases) {
- ++ID;
- fs::path p(TC.input);
- const fs::path output = p.lexically_normal();
- if (!PathEq(output, TC.expect)) {
- Failed = true;
- std::cerr << "TEST CASE #" << ID << " FAILED: \n";
- std::cerr << " Input: '" << TC.input << "'\n";
- std::cerr << " Expected: '" << TC.expect << "'\n";
- std::cerr << " Output: '" << output.native() << "'";
- std::cerr << std::endl;
- }
- }
- return Failed;
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path lexically_relative(const path& p) const;
-// path lexically_proximate(const path& p) const;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <iostream>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-int main() {
- // clang-format off
- struct {
- std::string input;
- std::string base;
- std::string expect;
- } TestCases[] = {
- {"", "", "."},
- {"/", "a", ""},
- {"a", "/", ""},
- {"//net", "a", ""},
- {"a", "//net", ""},
- {"//net/", "//net", ""},
- {"//net", "//net/", ".."},
- {"//base", "a", ""},
- {"a", "a", "."},
- {"a/b", "a/b", "."},
- {"a/b/c/", "a/b/c/", "."},
- {"//net", "//net", "."},
- {"//net/", "//net/", "."},
- {"//net/a/b", "//net/a/b", "."},
- {"/a/d", "/a/b/c", "../../d"},
- {"/a/b/c", "/a/d", "../b/c"},
- {"a/b/c", "a", "b/c"},
- {"a/b/c", "a/b/c/x/y", "../.."},
- {"a/b/c", "a/b/c", "."},
- {"a/b", "c/d", "../../a/b"}
- };
- // clang-format on
- int ID = 0;
- bool Failed = false;
- for (auto& TC : TestCases) {
- ++ID;
- const fs::path p(TC.input);
- const fs::path output = p.lexically_relative(TC.base);
- auto ReportErr = [&](const char* Testing, fs::path const& Output,
- fs::path const& Expected) {
- Failed = true;
- std::cerr << "TEST CASE #" << ID << " FAILED: \n";
- std::cerr << " Testing: " << Testing << "\n";
- std::cerr << " Input: '" << TC.input << "'\n";
- std::cerr << " Base: '" << TC.base << "'\n";
- std::cerr << " Expected: '" << Expected << "'\n";
- std::cerr << " Output: '" << Output.native() << "'";
- std::cerr << std::endl;
- };
- if (!PathEq(output, TC.expect))
- ReportErr("path::lexically_relative", output, TC.expect);
- const fs::path proximate_output = p.lexically_proximate(TC.base);
- // [path.gen] lexically_proximate
- // Returns: If the value of lexically_relative(base) is not an empty path,
- // return it.Otherwise return *this.
- const fs::path proximate_expected = output.native().empty() ? p
- : output;
- if (!PathEq(proximate_expected, proximate_output))
- ReportErr("path::lexically_proximate", proximate_output, proximate_expected);
- }
- return Failed;
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class ECharT, class Traits = char_traits<ECharT>,
-// class Allocator = allocator<ECharT>>
-// basic_string<ECharT, Traits, Allocator>
-// generic_string(const Allocator& a = Allocator()) const;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "min_allocator.h"
-#include "filesystem_test_helper.hpp"
-
-MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-
-
-// generic_string<C, T, A> forwards to string<C, T, A>. Tests for
-// string<C, T, A>() are in "path.native.op/string_alloc.pass.cpp".
-// generic_string is minimally tested here.
-int main()
-{
- using namespace fs;
- using CharT = wchar_t;
- using Traits = std::char_traits<CharT>;
- using Alloc = malloc_allocator<CharT>;
- using Str = std::basic_string<CharT, Traits, Alloc>;
- const wchar_t* expect = longString;
- const path p((const char*)longString);
- {
- DisableAllocationGuard g;
- Alloc a;
- Alloc::disable_default_constructor = true;
- Str s = p.generic_string<wchar_t, Traits, Alloc>(a);
- assert(s == expect);
- assert(Alloc::alloc_count > 0);
- assert(Alloc::outstanding_alloc() == 1);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// std::string generic_string() const;
-// std::wstring generic_wstring() const;
-// std::u8string generic_u8string() const;
-// std::u16string generic_u16string() const;
-// std::u32string generic_u32string() const;
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "min_allocator.h"
-#include "filesystem_test_helper.hpp"
-
-MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-
-int main()
-{
- using namespace fs;
- auto const& MS = longString;
- const char* value = longString;
- const path p(value);
- {
- std::string s = p.generic_string();
- assert(s == value);
- }
- {
- std::string s = p.generic_u8string();
- assert(s == (const char*)MS);
- }
- {
- std::wstring s = p.generic_wstring();
- assert(s == (const wchar_t*)MS);
- }
- {
- std::u16string s = p.generic_u16string();
- assert(s == (const char16_t*)MS);
- }
- {
- std::u32string s = p.generic_u32string();
- assert(s == (const char32_t*)MS);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// void clear() noexcept
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-int main() {
- using namespace fs;
- {
- path p;
- ASSERT_NOEXCEPT(p.clear());
- ASSERT_SAME_TYPE(void, decltype(p.clear()));
- p.clear();
- assert(p.empty());
- }
- {
- const path p("/foo/bar/baz");
- path p2(p);
- assert(p == p2);
- p2.clear();
- assert(p2.empty());
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& make_preferred()
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-struct MakePreferredTestcase {
- const char* value;
-};
-
-const MakePreferredTestcase TestCases[] =
- {
- {""}
- , {"hello_world"}
- , {"/"}
- , {"/foo/bar/baz/"}
- , {"\\"}
- , {"\\foo\\bar\\baz\\"}
- , {"\\foo\\/bar\\/baz\\"}
- };
-
-int main()
-{
- // This operation is an identity operation on linux.
- using namespace fs;
- for (auto const & TC : TestCases) {
- path p(TC.value);
- assert(p == TC.value);
- path& Ref = (p.make_preferred());
- assert(p.native() == TC.value);
- assert(&Ref == &p);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& remove_filename()
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-#include "verbose_assert.h"
-
-struct RemoveFilenameTestcase {
- const char* value;
- const char* expect;
-};
-
-const RemoveFilenameTestcase TestCases[] =
- {
- {"", ""}
- , {"/", "/"}
- , {"//", "//"}
- , {"///", "///"}
- , {"\\", ""}
- , {".", ""}
- , {"..", ""}
- , {"/foo", "/"}
- , {"foo/bar", "foo/"}
- , {"foo/", "foo/"}
- , {"//foo", "//"}
- , {"//foo/", "//foo/"}
- , {"//foo///", "//foo///"}
- , {"///foo", "///"}
- , {"///foo/", "///foo/"}
- , {"/foo/", "/foo/"}
- , {"/foo/.", "/foo/"}
- , {"/foo/..", "/foo/"}
- , {"/foo/////", "/foo/////"}
- , {"/foo\\\\", "/"}
- , {"/foo//\\/", "/foo//\\/"}
- , {"///foo", "///"}
- , {"file.txt", ""}
- , {"bar/../baz/./file.txt", "bar/../baz/./"}
- };
-
-int main()
-{
- using namespace fs;
- for (auto const & TC : TestCases) {
- path const p_orig(TC.value);
- path p(p_orig);
- assert(p == TC.value);
- path& Ref = (p.remove_filename());
- ASSERT_EQ(p, TC.expect) << DISPLAY(p_orig);
- assert(&Ref == &p);
- assert(!p.has_filename());
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& replace_extension(path const& p = path())
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-struct ReplaceExtensionTestcase {
- const char* value;
- const char* expect;
- const char* extension;
-};
-
-const ReplaceExtensionTestcase TestCases[] =
- {
- {"", "", ""}
- , {"foo.cpp", "foo", ""}
- , {"foo.cpp", "foo.", "."}
- , {"foo..cpp", "foo..txt", "txt"}
- , {"", ".txt", "txt"}
- , {"", ".txt", ".txt"}
- , {"/foo", "/foo.txt", ".txt"}
- , {"/foo", "/foo.txt", "txt"}
- , {"/foo.cpp", "/foo.txt", ".txt"}
- , {"/foo.cpp", "/foo.txt", "txt"}
- };
-const ReplaceExtensionTestcase NoArgCases[] =
- {
- {"", "", ""}
- , {"foo", "foo", ""}
- , {"foo.cpp", "foo", ""}
- , {"foo..cpp", "foo.", ""}
-};
-
-int main()
-{
- using namespace fs;
- for (auto const & TC : TestCases) {
- path p(TC.value);
- assert(p == TC.value);
- path& Ref = (p.replace_extension(TC.extension));
- assert(p == TC.expect);
- assert(&Ref == &p);
- }
- for (auto const& TC : NoArgCases) {
- path p(TC.value);
- assert(p == TC.value);
- path& Ref = (p.replace_extension());
- assert(p == TC.expect);
- assert(&Ref == &p);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// path& replace_filename()
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-#include "assert_checkpoint.h"
-#include "verbose_assert.h"
-
-struct ReplaceFilenameTestcase {
- const char* value;
- const char* expect;
- const char* filename;
-};
-
-const ReplaceFilenameTestcase TestCases[] =
- {
- {"/foo", "/bar", "bar"}
- , {"/foo", "/", ""}
- , {"foo", "bar", "bar"}
- , {"/", "/bar", "bar"}
- , {"\\", "bar", "bar"}
- , {"///", "///bar", "bar"}
- , {"\\\\", "bar", "bar"}
- , {"\\/\\", "\\/bar", "bar"}
- , {".", "bar", "bar"}
- , {"..", "bar", "bar"}
- , {"/foo\\baz/bong/", "/foo\\baz/bong/bar", "bar"}
- , {"/foo\\baz/bong", "/foo\\baz/bar", "bar"}
- };
-
-int main()
-{
- using namespace fs;
- for (auto const & TC : TestCases) {
- path p(TC.value);
- ASSERT_EQ(p, TC.value);
- path& Ref = (p.replace_filename(TC.filename));
- ASSERT_EQ(p, TC.expect)
- << DISPLAY(TC.value)
- << DISPLAY(TC.filename);
- assert(&Ref == &p);
- // Tests Effects "as-if": remove_filename() append(filename)
- {
- path p2(TC.value);
- path replace(TC.filename);
- p2.remove_filename();
- p2 /= replace;
- ASSERT_EQ(p, p2);
- }
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// void swap(path& rhs) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-struct SwapTestcase {
- const char* value1;
- const char* value2;
-};
-
-#define LONG_STR1 "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG"
-#define LONG_STR2 "_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2"
-const SwapTestcase TestCases[] =
- {
- {"", ""}
- , {"shortstr", LONG_STR1}
- , {LONG_STR1, "shortstr"}
- , {LONG_STR1, LONG_STR2}
- };
-#undef LONG_STR1
-#undef LONG_STR2
-
-int main()
-{
- using namespace fs;
- {
- path p;
- ASSERT_NOEXCEPT(p.swap(p));
- ASSERT_SAME_TYPE(void, decltype(p.swap(p)));
- }
- for (auto const & TC : TestCases) {
- path p1(TC.value1);
- path p2(TC.value2);
- {
- DisableAllocationGuard g;
- p1.swap(p2);
- }
- assert(p1 == TC.value2);
- assert(p2 == TC.value1);
- {
- DisableAllocationGuard g;
- p1.swap(p2);
- }
- assert(p1 == TC.value1);
- assert(p2 == TC.value2);
- }
- // self-swap
- {
- const char* Val = "aoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeu";
- path p1(Val);
- assert(p1 == Val);
- {
- DisableAllocationGuard g;
- p1.swap(p1);
- }
- assert(p1 == Val);
- }
-}
+++ /dev/null
-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// const value_type* c_str() const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "filesystem_test_helper.hpp"
-
-
-int main()
-{
- using namespace fs;
- const char* const value = "hello world";
- const std::string str_value = value;
- { // Check signature
- path p(value);
- ASSERT_SAME_TYPE(path::value_type const*, decltype(p.c_str()));
- ASSERT_NOEXCEPT(p.c_str());
- }
- {
- path p(value);
- assert(p.c_str() == str_value);
- assert(p.native().c_str() == p.c_str());
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// std::string string() const;
-// std::wstring wstring() const;
-// std::u8string u8string() const;
-// std::u16string u16string() const;
-// std::u32string u32string() const;
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "min_allocator.h"
-#include "filesystem_test_helper.hpp"
-
-
-MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-
-int main()
-{
- using namespace fs;
- auto const& MS = longString;
- const char* value = longString;
- const path p(value);
- {
- std::string s = p.string();
- assert(s == value);
- }
- {
- std::string s = p.u8string();
- assert(s == (const char*)MS);
- }
- {
- std::wstring s = p.wstring();
- assert(s == (const wchar_t*)MS);
- }
- {
- std::u16string s = p.u16string();
- assert(s == (const char16_t*)MS);
- }
- {
- std::u32string s = p.u32string();
- assert(s == (const char32_t*)MS);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// const string_type& native() const noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "filesystem_test_helper.hpp"
-
-
-int main()
-{
- using namespace fs;
- const char* const value = "hello world";
- { // Check signature
- path p(value);
- ASSERT_SAME_TYPE(path::string_type const&, decltype(p.native()));
- ASSERT_NOEXCEPT(p.native());
- }
- { // native() is tested elsewhere
- path p(value);
- assert(p.native() == value);
- }
-}
+++ /dev/null
-
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// operator string_type() const;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "filesystem_test_helper.hpp"
-
-
-int main()
-{
- using namespace fs;
- using string_type = path::string_type;
- const char* const value = "hello world";
- { // Check signature
- path p(value);
- static_assert(std::is_convertible<path, string_type>::value, "");
- static_assert(std::is_constructible<string_type, path>::value, "");
- ASSERT_SAME_TYPE(string_type, decltype(p.operator string_type()));
- ASSERT_NOT_NOEXCEPT(p.operator string_type());
- }
- {
- path p(value);
- assert(p.native() == value);
- string_type s = p;
- assert(s == value);
- assert(p == value);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class ECharT, class Traits = char_traits<ECharT>,
-// class Allocator = allocator<ECharT>>
-// basic_string<ECharT, Traits, Allocator>
-// string(const Allocator& a = Allocator()) const;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "min_allocator.h"
-#include "filesystem_test_helper.hpp"
-
-
-// the SSO is always triggered for strings of size 2.
-MultiStringType shortString = MKSTR("a");
-MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
-
-template <class CharT>
-void doShortStringTest(MultiStringType const& MS) {
- using namespace fs;
- using Ptr = CharT const*;
- using Str = std::basic_string<CharT>;
- using Alloc = std::allocator<CharT>;
- Ptr value = MS;
- const path p((const char*)MS);
- {
- DisableAllocationGuard g;
- Str s = p.string<CharT>();
- assert(s == value);
- Str s2 = p.string<CharT>(Alloc{});
- assert(s2 == value);
- }
- using MAlloc = malloc_allocator<CharT>;
- MAlloc::reset();
- {
- using Traits = std::char_traits<CharT>;
- using AStr = std::basic_string<CharT, Traits, MAlloc>;
- DisableAllocationGuard g;
- AStr s = p.string<CharT, Traits, MAlloc>();
- assert(s == value);
- assert(MAlloc::alloc_count == 0);
- assert(MAlloc::outstanding_alloc() == 0);
- }
- MAlloc::reset();
- { // Other allocator - provided copy
- using Traits = std::char_traits<CharT>;
- using AStr = std::basic_string<CharT, Traits, MAlloc>;
- DisableAllocationGuard g;
- MAlloc a;
- // don't allow another allocator to be default constructed.
- MAlloc::disable_default_constructor = true;
- AStr s = p.string<CharT, Traits, MAlloc>(a);
- assert(s == value);
- assert(MAlloc::alloc_count == 0);
- assert(MAlloc::outstanding_alloc() == 0);
- }
- MAlloc::reset();
-}
-
-template <class CharT>
-void doLongStringTest(MultiStringType const& MS) {
- using namespace fs;
- using Ptr = CharT const*;
- using Str = std::basic_string<CharT>;
- Ptr value = MS;
- const path p((const char*)MS);
- { // Default allocator
- using Alloc = std::allocator<CharT>;
- Str s = p.string<CharT>();
- assert(s == value);
- Str s2 = p.string<CharT>(Alloc{});
- assert(s2 == value);
- }
- using MAlloc = malloc_allocator<CharT>;
- MAlloc::reset();
- { // Other allocator - default construct
- using Traits = std::char_traits<CharT>;
- using AStr = std::basic_string<CharT, Traits, MAlloc>;
- DisableAllocationGuard g;
- AStr s = p.string<CharT, Traits, MAlloc>();
- assert(s == value);
- assert(MAlloc::alloc_count > 0);
- assert(MAlloc::outstanding_alloc() == 1);
- }
- MAlloc::reset();
- { // Other allocator - provided copy
- using Traits = std::char_traits<CharT>;
- using AStr = std::basic_string<CharT, Traits, MAlloc>;
- DisableAllocationGuard g;
- MAlloc a;
- // don't allow another allocator to be default constructed.
- MAlloc::disable_default_constructor = true;
- AStr s = p.string<CharT, Traits, MAlloc>(a);
- assert(s == value);
- assert(MAlloc::alloc_count > 0);
- assert(MAlloc::outstanding_alloc() == 1);
- }
- MAlloc::reset();
- /////////////////////////////////////////////////////////////////////////////
-}
-
-int main()
-{
- using namespace fs;
- {
- auto const& S = shortString;
- doShortStringTest<char>(S);
- doShortStringTest<wchar_t>(S);
- doShortStringTest<char16_t>(S);
- doShortStringTest<char32_t>(S);
- }
- {
- auto const& S = longString;
- doLongStringTest<char>(S);
- doLongStringTest<wchar_t>(S);
- doLongStringTest<char16_t>(S);
- doLongStringTest<char32_t>(S);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-//-------------------------------
-// 8.4.10 path query [path.query]
-//-------------------------------
-// bool empty() const noexcept;
-// bool has_root_path() const;
-// bool has_root_name() const;
-// bool has_root_directory() const;
-// bool has_relative_path() const;
-// bool has_parent_path() const;
-// bool has_filename() const;
-// bool has_stem() const;
-// bool has_extension() const;
-// bool is_absolute() const;
-// bool is_relative() const;
-
-// tested in path.decompose
-int main() {}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path operator/(path const&, path const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "filesystem_test_helper.hpp"
-
-
-// This is mainly tested via the member append functions.
-int main()
-{
- using namespace fs;
- path p1("abc");
- path p2("def");
- path p3 = p1 / p2;
- assert(p3 == "abc/def");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// The comparison operators are tested as part of [path.compare]
-// in class.path/path.members/path.compare.pass.cpp
-int main() {}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// The "hash_value" function is tested as part of [path.compare]
-// in class.path/path.members/path.compare.pass.cpp
-int main() {}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// template <class Source>
-// path u8path(Source const&);
-// template <class InputIter>
-// path u8path(InputIter, InputIter);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-int main()
-{
- using namespace fs;
- const char* In1 = "abcd/efg";
- const std::string In2(In1);
- const auto In3 = In2.begin();
- const auto In3End = In2.end();
- {
- path p = fs::u8path(In1);
- assert(p == In1);
- }
- {
- path p = fs::u8path(In2);
- assert(p == In1);
- }
- {
- path p = fs::u8path(In3);
- assert(p == In1);
- }
- {
- path p = fs::u8path(In3, In3End);
- assert(p == In1);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class charT, class traits>
-// basic_ostream<charT, traits>&
-// operator<<(basic_ostream<charT, traits>& os, const path& p);
-//
-// template <class charT, class traits>
-// basic_istream<charT, traits>&
-// operator>>(basic_istream<charT, traits>& is, path& p)
-//
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <sstream>
-#include <cassert>
-#include <iostream>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
-MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
-
-
-
-template <class CharT>
-void doIOTest() {
- using namespace fs;
- using Ptr = const CharT*;
- using StrStream = std::basic_stringstream<CharT>;
- const Ptr E = OutStr;
- const path p((const char*)InStr);
- StrStream ss;
- { // test output
- auto& ret = (ss << p);
- assert(ss.str() == E);
- assert(&ret == &ss);
- }
- { // test input
- path p_in;
- auto& ret = ss >> p_in;
- assert(p_in.native() == (const char*)InStr);
- assert(&ret == &ss);
- }
-}
-
-namespace impl {
-using namespace fs;
-
-template <class Stream, class Tp, class = decltype(std::declval<Stream&>() << std::declval<Tp&>())>
-std::true_type is_ostreamable_imp(int);
-
-template <class Stream, class Tp>
-std::false_type is_ostreamable_imp(long);
-
-template <class Stream, class Tp, class = decltype(std::declval<Stream&>() >> std::declval<Tp&>())>
-std::true_type is_istreamable_imp(int);
-
-template <class Stream, class Tp>
-std::false_type is_istreamable_imp(long);
-
-
-} // namespace impl
-
-template <class Stream, class Tp>
-struct is_ostreamable : decltype(impl::is_ostreamable_imp<Stream, Tp>(0)) {};
-template <class Stream, class Tp>
-struct is_istreamable : decltype(impl::is_istreamable_imp<Stream, Tp>(0)) {};
-
-void test_LWG2989() {
- static_assert(!is_ostreamable<decltype(std::cout), std::wstring>::value, "");
- static_assert(!is_ostreamable<decltype(std::wcout), std::string>::value, "");
- static_assert(!is_istreamable<decltype(std::cin), std::wstring>::value, "");
- static_assert(!is_istreamable<decltype(std::wcin), std::string>::value, "");
-}
-
-int main() {
- doIOTest<char>();
- doIOTest<wchar_t>();
- //doIOTest<char16_t>();
- //doIOTest<char32_t>();
- test_LWG2989();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// template <class charT, class traits>
-// basic_ostream<charT, traits>&
-// operator<<(basic_ostream<charT, traits>& os, const path& p);
-//
-// template <class charT, class traits>
-// basic_istream<charT, traits>&
-// operator>>(basic_istream<charT, traits>& is, path& p)
-//
-
-// TODO(EricWF) This test fails because "std::quoted" fails to compile
-// for char16_t and char32_t types. Combine with path.io.pass.cpp when this
-// passes.
-// XFAIL: *
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <sstream>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
-MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
-
-template <class CharT>
-void doIOTest() {
- using namespace fs;
- using Ptr = const CharT*;
- using StrStream = std::basic_stringstream<CharT>;
- const char* const InCStr = InStr;
- const Ptr E = OutStr;
- const path p((const char*)InStr);
- StrStream ss;
- { // test output
- auto& ret = (ss << p);
- assert(ss.str() == E);
- assert(&ret == &ss);
- }
- { // test input
- path p_in;
- auto& ret = ss >> p_in;
- assert(p_in.native() == (const char*)InStr);
- assert(&ret == &ss);
- }
-}
-
-
-int main() {
- doIOTest<char16_t>();
- doIOTest<char32_t>();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void swap(path& lhs, path& rhs) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-// NOTE: this is tested in path.members/path.modifiers via the member swap.
-int main()
-{
- using namespace fs;
- const char* value1 = "foo/bar/baz";
- const char* value2 = "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG";
- path p1(value1);
- path p2(value2);
- {
- using namespace std; using namespace fs;
- ASSERT_NOEXCEPT(swap(p1, p2));
- ASSERT_SAME_TYPE(void, decltype(swap(p1, p2)));
- }
- {
- DisableAllocationGuard g;
- using namespace std;
- using namespace fs;
- swap(p1, p2);
- assert(p1.native() == value2);
- assert(p2.native() == value1);
- swap(p1, p2);
- assert(p1.native() == value1);
- assert(p2.native() == value2);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path
-
-// typedef ... value_type;
-// typedef basic_string<value_type> string_type;
-// static constexpr value_type preferred_separator = ...;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-int main() {
- using namespace fs;
- ASSERT_SAME_TYPE(path::value_type, char);
- ASSERT_SAME_TYPE(path::string_type, std::basic_string<path::value_type>);
- {
- ASSERT_SAME_TYPE(const path::value_type, decltype(path::preferred_separator));
- static_assert(path::preferred_separator == '/', "");
- // Make preferred_separator ODR used by taking its address.
- const char* dummy = &path::preferred_separator;
- ((void)dummy);
- }
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// recursive_recursive_directory_iterator(recursive_recursive_directory_iterator const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_copy_construct_tests)
-
-TEST_CASE(test_constructor_signature)
-{
- using D = recursive_directory_iterator;
- static_assert(std::is_copy_constructible<D>::value, "");
- //static_assert(!std::is_nothrow_copy_constructible<D>::value, "");
-}
-
-TEST_CASE(test_copy_end_iterator)
-{
- const recursive_directory_iterator endIt;
- recursive_directory_iterator it(endIt);
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(test_copy_valid_iterator)
-{
- const path testDir = StaticEnv::Dir;
- const recursive_directory_iterator endIt{};
-
- // build 'it' up with "interesting" non-default state so we can test
- // that it gets copied. We want to get 'it' into a state such that:
- // it.options() != directory_options::none
- // it.depth() != 0
- // it.recursion_pending() != true
- const directory_options opts = directory_options::skip_permission_denied;
- recursive_directory_iterator it(testDir, opts);
- TEST_REQUIRE(it != endIt);
- while (it.depth() == 0) {
- ++it;
- TEST_REQUIRE(it != endIt);
- }
- it.disable_recursion_pending();
- TEST_CHECK(it.options() == opts);
- TEST_CHECK(it.depth() == 1);
- TEST_CHECK(it.recursion_pending() == false);
- const path entry = *it;
-
- // OPERATION UNDER TEST //
- const recursive_directory_iterator it2(it);
- // ------------------- //
-
- TEST_REQUIRE(it2 == it);
- TEST_CHECK(*it2 == entry);
- TEST_CHECK(it2.depth() == 1);
- TEST_CHECK(it2.recursion_pending() == false);
- TEST_CHECK(it != endIt);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// recursive_directory_iterator& operator=(recursive_directory_iterator const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_copy_assign_tests)
-
-recursive_directory_iterator createInterestingIterator()
- // Create an "interesting" iterator where all fields are
- // in a non-default state. The returned 'it' is in a
- // state such that:
- // it.options() == directory_options::skip_permission_denied
- // it.depth() == 1
- // it.recursion_pending() == true
-{
- const path testDir = StaticEnv::Dir;
- const recursive_directory_iterator endIt;
- recursive_directory_iterator it(testDir,
- directory_options::skip_permission_denied);
- TEST_ASSERT(it != endIt);
- while (it.depth() != 1) {
- ++it;
- TEST_ASSERT(it != endIt);
- }
- TEST_ASSERT(it.depth() == 1);
- it.disable_recursion_pending();
- return it;
-}
-
-
-recursive_directory_iterator createDifferentInterestingIterator()
- // Create an "interesting" iterator where all fields are
- // in a non-default state. The returned 'it' is in a
- // state such that:
- // it.options() == directory_options::follow_directory_symlink
- // it.depth() == 2
- // it.recursion_pending() == false
-{
- const path testDir = StaticEnv::Dir;
- const recursive_directory_iterator endIt;
- recursive_directory_iterator it(testDir,
- directory_options::follow_directory_symlink);
- TEST_ASSERT(it != endIt);
- while (it.depth() != 2) {
- ++it;
- TEST_ASSERT(it != endIt);
- }
- TEST_ASSERT(it.depth() == 2);
- return it;
-}
-
-TEST_CASE(test_assignment_signature) {
- using D = recursive_directory_iterator;
- static_assert(std::is_copy_assignable<D>::value, "");
-}
-
-TEST_CASE(test_copy_to_end_iterator)
-{
- const recursive_directory_iterator endIt;
-
- const recursive_directory_iterator from = createInterestingIterator();
- const path entry = *from;
-
- recursive_directory_iterator to;
- to = from;
- TEST_REQUIRE(to == from);
- TEST_CHECK(*to == entry);
- TEST_CHECK(to.options() == from.options());
- TEST_CHECK(to.depth() == from.depth());
- TEST_CHECK(to.recursion_pending() == from.recursion_pending());
-}
-
-
-TEST_CASE(test_copy_from_end_iterator)
-{
- const recursive_directory_iterator from;
- recursive_directory_iterator to = createInterestingIterator();
-
- to = from;
- TEST_REQUIRE(to == from);
- TEST_CHECK(to == recursive_directory_iterator{});
-}
-
-TEST_CASE(test_copy_valid_iterator)
-{
- const recursive_directory_iterator endIt;
-
- const recursive_directory_iterator it = createInterestingIterator();
- const path entry = *it;
-
- recursive_directory_iterator it2 = createDifferentInterestingIterator();
- TEST_REQUIRE(it2 != it);
- TEST_CHECK(it2.options() != it.options());
- TEST_CHECK(it2.depth() != it.depth());
- TEST_CHECK(it2.recursion_pending() != it.recursion_pending());
- TEST_CHECK(*it2 != entry);
-
- it2 = it;
- TEST_REQUIRE(it2 == it);
- TEST_CHECK(it2.options() == it.options());
- TEST_CHECK(it2.depth() == it.depth());
- TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
- TEST_CHECK(*it2 == entry);
-}
-
-TEST_CASE(test_returns_reference_to_self)
-{
- const recursive_directory_iterator it;
- recursive_directory_iterator it2;
- recursive_directory_iterator& ref = (it2 = it);
- TEST_CHECK(&ref == &it2);
-}
-
-TEST_CASE(test_self_copy)
-{
- // Create two non-equal iterators that have exactly the same state.
- recursive_directory_iterator it = createInterestingIterator();
- recursive_directory_iterator it2 = createInterestingIterator();
- TEST_CHECK(it != it2);
- TEST_CHECK(it2.options() == it.options());
- TEST_CHECK(it2.depth() == it.depth());
- TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
- TEST_CHECK(*it2 == *it);
-
- // perform a self-copy and check that the state still matches the
- // other unmodified iterator.
- recursive_directory_iterator const& cit = it;
- it = cit;
- TEST_CHECK(it2.options() == it.options());
- TEST_CHECK(it2.depth() == it.depth());
- TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
- TEST_CHECK(*it2 == *it);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class directory_iterator
-
-//
-// explicit recursive_directory_iterator(const path& p);
-// recursive_directory_iterator(const path& p, directory_options options);
-// recursive_directory_iterator(const path& p, error_code& ec);
-// recursive_directory_iterator(const path& p, directory_options options, error_code& ec);
-
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-using RDI = recursive_directory_iterator;
-
-TEST_SUITE(recursive_directory_iterator_constructor_tests)
-
-TEST_CASE(test_constructor_signatures)
-{
- using D = recursive_directory_iterator;
-
- // explicit directory_iterator(path const&);
- static_assert(!std::is_convertible<path, D>::value, "");
- static_assert(std::is_constructible<D, path>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path>::value, "");
-
- // directory_iterator(path const&, error_code&)
- static_assert(std::is_constructible<D, path,
- std::error_code&>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path,
- std::error_code&>::value, "");
-
- // directory_iterator(path const&, directory_options);
- static_assert(std::is_constructible<D, path, directory_options>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
-
- // directory_iterator(path const&, directory_options, error_code&)
- static_assert(std::is_constructible<D, path, directory_options, std::error_code&>::value, "");
- static_assert(!std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, "");
-}
-
-TEST_CASE(test_construction_from_bad_path)
-{
- std::error_code ec;
- directory_options opts = directory_options::none;
- const RDI endIt;
-
- const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink };
- for (path const& testPath : testPaths)
- {
- {
- RDI it(testPath, ec);
- TEST_CHECK(ec);
- TEST_CHECK(it == endIt);
- }
- {
- RDI it(testPath, opts, ec);
- TEST_CHECK(ec);
- TEST_CHECK(it == endIt);
- }
- {
- TEST_CHECK_THROW(filesystem_error, RDI(testPath));
- TEST_CHECK_THROW(filesystem_error, RDI(testPath, opts));
- }
- }
-}
-
-TEST_CASE(access_denied_test_case)
-{
- using namespace fs;
- scoped_test_env env;
- path const testDir = env.make_env_path("dir1");
- path const testFile = testDir / "testFile";
- env.create_dir(testDir);
- env.create_file(testFile, 42);
-
- // Test that we can iterator over the directory before changing the perms
- {
- RDI it(testDir);
- TEST_REQUIRE(it != RDI{});
- }
-
- // Change the permissions so we can no longer iterate
- permissions(testDir, perms::none);
-
- // Check that the construction fails when skip_permissions_denied is
- // not given.
- {
- std::error_code ec;
- RDI it(testDir, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == RDI{});
- }
- // Check that construction does not report an error when
- // 'skip_permissions_denied' is given.
- {
- std::error_code ec;
- RDI it(testDir, directory_options::skip_permission_denied, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it == RDI{});
- }
-}
-
-
-TEST_CASE(access_denied_to_file_test_case)
-{
- using namespace fs;
- scoped_test_env env;
- path const testFile = env.make_env_path("file1");
- env.create_file(testFile, 42);
-
- // Change the permissions so we can no longer iterate
- permissions(testFile, perms::none);
-
- // Check that the construction fails when skip_permissions_denied is
- // not given.
- {
- std::error_code ec;
- RDI it(testFile, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == RDI{});
- }
- // Check that construction still fails when 'skip_permissions_denied' is given
- // because we tried to open a file and not a directory.
- {
- std::error_code ec;
- RDI it(testFile, directory_options::skip_permission_denied, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == RDI{});
- }
-}
-
-TEST_CASE(test_open_on_empty_directory_equals_end)
-{
- scoped_test_env env;
- const path testDir = env.make_env_path("dir1");
- env.create_dir(testDir);
-
- const RDI endIt;
- {
- std::error_code ec;
- RDI it(testDir, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(it == endIt);
- }
- {
- RDI it(testDir);
- TEST_CHECK(it == endIt);
- }
-}
-
-TEST_CASE(test_open_on_directory_succeeds)
-{
- const path testDir = StaticEnv::Dir;
- std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
- std::end( StaticEnv::DirIterationList));
- const RDI endIt{};
-
- {
- std::error_code ec;
- RDI it(testDir, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it != endIt);
- TEST_CHECK(dir_contents.count(*it));
- }
- {
- RDI it(testDir);
- TEST_CHECK(it != endIt);
- TEST_CHECK(dir_contents.count(*it));
- }
-}
-
-TEST_CASE(test_open_on_file_fails)
-{
- const path testFile = StaticEnv::File;
- const RDI endIt{};
- {
- std::error_code ec;
- RDI it(testFile, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(it == endIt);
- }
- {
- TEST_CHECK_THROW(filesystem_error, RDI(testFile));
- }
-}
-
-TEST_CASE(test_options_post_conditions)
-{
- const path goodDir = StaticEnv::Dir;
- const path badDir = StaticEnv::DNE;
-
- {
- std::error_code ec;
-
- RDI it1(goodDir, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it1.options() == directory_options::none);
-
- RDI it2(badDir, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(it2 == RDI{});
- }
- {
- std::error_code ec;
- const directory_options opts = directory_options::skip_permission_denied;
-
- RDI it1(goodDir, opts, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it1.options() == opts);
-
- RDI it2(badDir, opts, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(it2 == RDI{});
- }
- {
- RDI it(goodDir);
- TEST_CHECK(it.options() == directory_options::none);
- }
- {
- const directory_options opts = directory_options::follow_directory_symlink;
- RDI it(goodDir, opts);
- TEST_CHECK(it.options() == opts);
- }
-}
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// int depth() const
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_depth_tests)
-
-TEST_CASE(test_depth)
-{
- const path testDir = StaticEnv::Dir;
- const path DirDepth1 = StaticEnv::Dir2;
- const path DirDepth2 = StaticEnv::Dir3;
- const recursive_directory_iterator endIt{};
-
- std::error_code ec;
- recursive_directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(it.depth() == 0);
-
- bool seen_d1, seen_d2;
- seen_d1 = seen_d2 = false;
-
- while (it != endIt) {
- const path entry = *it;
- const path parent = entry.parent_path();
- if (parent == testDir) {
- TEST_CHECK(it.depth() == 0);
- } else if (parent == DirDepth1) {
- TEST_CHECK(it.depth() == 1);
- seen_d1 = true;
- } else if (parent == DirDepth2) {
- TEST_CHECK(it.depth() == 2);
- seen_d2 = true;
- } else {
- TEST_CHECK(!"Unexpected depth while iterating over static env");
- }
- ++it;
- }
- TEST_REQUIRE(seen_d1 && seen_d2);
- TEST_CHECK(it == endIt);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// void disable_recursion_pending();
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_disable_recursion_pending_tests)
-
-// NOTE: The main semantics of disable_recursion_pending are tested
-// in the 'recursion_pending()' tests.
-TEST_CASE(basic_test)
-{
- recursive_directory_iterator it(StaticEnv::Dir);
- TEST_REQUIRE(it.recursion_pending() == true);
- it.disable_recursion_pending();
- TEST_CHECK(it.recursion_pending() == false);
- it.disable_recursion_pending();
- TEST_CHECK(it.recursion_pending() == false);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// recursive_directory_iterator& operator++();
-// recursive_directory_iterator& increment(error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_increment_tests)
-
-TEST_CASE(test_increment_signatures)
-{
- using D = recursive_directory_iterator;
- recursive_directory_iterator d; ((void)d);
- std::error_code ec; ((void)ec);
-
- ASSERT_SAME_TYPE(decltype(++d), recursive_directory_iterator&);
- ASSERT_NOT_NOEXCEPT(++d);
-
- ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&);
- ASSERT_NOT_NOEXCEPT(d.increment(ec));
-}
-
-TEST_CASE(test_prefix_increment)
-{
- const path testDir = StaticEnv::Dir;
- const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
- std::end( StaticEnv::RecDirIterationList));
- const recursive_directory_iterator endIt{};
-
- std::error_code ec;
- recursive_directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- recursive_directory_iterator& it_ref = ++it;
- TEST_CHECK(&it_ref == &it);
- }
-
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(test_postfix_increment)
-{
- const path testDir = StaticEnv::Dir;
- const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
- std::end( StaticEnv::RecDirIterationList));
- const recursive_directory_iterator endIt{};
-
- std::error_code ec;
- recursive_directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- const path entry2 = *it++;
- TEST_CHECK(entry2 == entry);
- }
- TEST_CHECK(it == endIt);
-}
-
-
-TEST_CASE(test_increment_method)
-{
- const path testDir = StaticEnv::Dir;
- const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
- std::end( StaticEnv::RecDirIterationList));
- const recursive_directory_iterator endIt{};
-
- std::error_code ec;
- recursive_directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- recursive_directory_iterator& it_ref = it.increment(ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(&it_ref == &it);
- }
-
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(test_follow_symlinks)
-{
- const path testDir = StaticEnv::Dir;
- auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList;
-
- const std::set<path> dir_contents(std::begin(IterList), std::end(IterList));
- const recursive_directory_iterator endIt{};
-
- std::error_code ec;
- recursive_directory_iterator it(testDir,
- directory_options::follow_directory_symlink, ec);
- TEST_REQUIRE(!ec);
-
- std::set<path> unseen_entries = dir_contents;
- while (!unseen_entries.empty()) {
- TEST_REQUIRE(it != endIt);
- const path entry = *it;
-
- TEST_REQUIRE(unseen_entries.erase(entry) == 1);
- recursive_directory_iterator& it_ref = it.increment(ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(&it_ref == &it);
- }
- TEST_CHECK(it == endIt);
-}
-
-TEST_CASE(access_denied_on_recursion_test_case)
-{
- using namespace fs;
- scoped_test_env env;
- const path testFiles[] = {
- env.create_dir("dir1"),
- env.create_dir("dir1/dir2"),
- env.create_file("dir1/dir2/file1"),
- env.create_file("dir1/file2")
- };
- const path startDir = testFiles[0];
- const path permDeniedDir = testFiles[1];
- const path otherFile = testFiles[3];
- auto SkipEPerm = directory_options::skip_permission_denied;
-
- // Change the permissions so we can no longer iterate
- permissions(permDeniedDir, perms::none);
-
- const recursive_directory_iterator endIt;
-
- // Test that recursion resulting in a "EACCESS" error is not ignored
- // by default.
- {
- std::error_code ec = GetTestEC();
- recursive_directory_iterator it(startDir, ec);
- TEST_REQUIRE(ec != GetTestEC());
- TEST_REQUIRE(!ec);
- while (it != endIt && it->path() != permDeniedDir)
- ++it;
- TEST_REQUIRE(it != endIt);
- TEST_REQUIRE(*it == permDeniedDir);
-
- it.increment(ec);
- TEST_CHECK(ec);
- TEST_CHECK(it == endIt);
- }
- // Same as above but test operator++().
- {
- std::error_code ec = GetTestEC();
- recursive_directory_iterator it(startDir, ec);
- TEST_REQUIRE(!ec);
- while (it != endIt && it->path() != permDeniedDir)
- ++it;
- TEST_REQUIRE(it != endIt);
- TEST_REQUIRE(*it == permDeniedDir);
-
- TEST_REQUIRE_THROW(filesystem_error, ++it);
- }
- // Test that recursion resulting in a "EACCESS" error is ignored when the
- // correct options are given to the constructor.
- {
- std::error_code ec = GetTestEC();
- recursive_directory_iterator it(startDir, SkipEPerm, ec);
- TEST_REQUIRE(!ec);
- TEST_REQUIRE(it != endIt);
-
- bool seenOtherFile = false;
- if (*it == otherFile) {
- ++it;
- seenOtherFile = true;
- TEST_REQUIRE (it != endIt);
- }
- TEST_REQUIRE(*it == permDeniedDir);
-
- ec = GetTestEC();
- it.increment(ec);
- TEST_REQUIRE(!ec);
-
- if (seenOtherFile) {
- TEST_CHECK(it == endIt);
- } else {
- TEST_CHECK(it != endIt);
- TEST_CHECK(*it == otherFile);
- }
- }
- // Test that construction resulting in a "EACCESS" error is not ignored
- // by default.
- {
- std::error_code ec;
- recursive_directory_iterator it(permDeniedDir, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(it == endIt);
- }
- // Same as above but testing the throwing constructors
- {
- TEST_REQUIRE_THROW(filesystem_error,
- recursive_directory_iterator(permDeniedDir));
- }
- // Test that construction resulting in a "EACCESS" error constructs the
- // end iterator when the correct options are given.
- {
- std::error_code ec = GetTestEC();
- recursive_directory_iterator it(permDeniedDir, SkipEPerm, ec);
- TEST_REQUIRE(!ec);
- TEST_REQUIRE(it == endIt);
- }
-}
-
-// See llvm.org/PR35078
-TEST_CASE(test_PR35078)
-{
- using namespace fs;
- scoped_test_env env;
- const path testFiles[] = {
- env.create_dir("dir1"),
- env.create_dir("dir1/dir2"),
- env.create_dir("dir1/dir2/dir3"),
- env.create_file("dir1/file1"),
- env.create_file("dir1/dir2/dir3/file2")
- };
- const path startDir = testFiles[0];
- const path permDeniedDir = testFiles[1];
- const path nestedDir = testFiles[2];
- const path nestedFile = testFiles[3];
-
- // Change the permissions so we can no longer iterate
- permissions(permDeniedDir,
- perms::group_exec|perms::owner_exec|perms::others_exec,
- perm_options::remove);
-
- const std::error_code eacess_ec =
- std::make_error_code(std::errc::permission_denied);
- std::error_code ec = GetTestEC();
-
- const recursive_directory_iterator endIt;
-
- auto SetupState = [&](bool AllowEAccess, bool& SeenFile3) {
- SeenFile3 = false;
- auto Opts = AllowEAccess ? directory_options::skip_permission_denied
- : directory_options::none;
- recursive_directory_iterator it(startDir, Opts, ec);
- while (!ec && it != endIt && *it != nestedDir) {
- if (*it == nestedFile)
- SeenFile3 = true;
- it.increment(ec);
- }
- return it;
- };
-
- {
- bool SeenNestedFile = false;
- recursive_directory_iterator it = SetupState(false, SeenNestedFile);
- TEST_REQUIRE(it != endIt);
- TEST_REQUIRE(*it == nestedDir);
- ec = GetTestEC();
- it.increment(ec);
- TEST_CHECK(ec);
- TEST_CHECK(ec == eacess_ec);
- TEST_CHECK(it == endIt);
- }
- {
- bool SeenNestedFile = false;
- recursive_directory_iterator it = SetupState(true, SeenNestedFile);
- TEST_REQUIRE(it != endIt);
- TEST_REQUIRE(*it == nestedDir);
- ec = GetTestEC();
- it.increment(ec);
- TEST_CHECK(!ec);
- if (SeenNestedFile) {
- TEST_CHECK(it == endIt);
- } else {
- TEST_REQUIRE(it != endIt);
- TEST_CHECK(*it == nestedFile);
- }
- }
- {
- bool SeenNestedFile = false;
- recursive_directory_iterator it = SetupState(false, SeenNestedFile);
- TEST_REQUIRE(it != endIt);
- TEST_REQUIRE(*it == nestedDir);
-
- ExceptionChecker Checker(std::errc::permission_denied,
- "recursive_directory_iterator::operator++()",
- format_string("attempting recursion into \"%s\"",
- nestedDir.native()));
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ++it);
- }
-}
-
-
-// See llvm.org/PR35078
-TEST_CASE(test_PR35078_with_symlink)
-{
- using namespace fs;
- scoped_test_env env;
- const path testFiles[] = {
- env.create_dir("dir1"),
- env.create_file("dir1/file1"),
- env.create_dir("sym_dir"),
- env.create_dir("sym_dir/nested_sym_dir"),
- env.create_symlink("sym_dir/nested_sym_dir", "dir1/dir2"),
- env.create_dir("sym_dir/dir1"),
- env.create_dir("sym_dir/dir1/dir2"),
-
- };
- // const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
- const path startDir = testFiles[0];
- const path nestedFile = testFiles[1];
- const path permDeniedDir = testFiles[2];
- const path symDir = testFiles[4];
-
- // Change the permissions so we can no longer iterate
- permissions(permDeniedDir,
- perms::group_exec|perms::owner_exec|perms::others_exec,
- perm_options::remove);
-
- const std::error_code eacess_ec =
- std::make_error_code(std::errc::permission_denied);
- std::error_code ec = GetTestEC();
-
- const recursive_directory_iterator endIt;
-
- auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenFile3) {
- SeenFile3 = false;
- auto Opts = AllowEAccess ? directory_options::skip_permission_denied
- : directory_options::none;
- if (FollowSym)
- Opts |= directory_options::follow_directory_symlink;
- recursive_directory_iterator it(startDir, Opts, ec);
- while (!ec && it != endIt && *it != symDir) {
- if (*it == nestedFile)
- SeenFile3 = true;
- it.increment(ec);
- }
- return it;
- };
-
- struct {
- bool SkipPermDenied;
- bool FollowSymlinks;
- bool ExpectSuccess;
- } TestCases[] = {
- // Passing cases
- {false, false, true}, {true, true, true}, {true, false, true},
- // Failing cases
- {false, true, false}
- };
- for (auto TC : TestCases) {
- bool SeenNestedFile = false;
- recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
- TC.FollowSymlinks,
- SeenNestedFile);
- TEST_REQUIRE(!ec);
- TEST_REQUIRE(it != endIt);
- TEST_REQUIRE(*it == symDir);
- ec = GetTestEC();
- it.increment(ec);
- if (TC.ExpectSuccess) {
- TEST_CHECK(!ec);
- if (SeenNestedFile) {
- TEST_CHECK(it == endIt);
- } else {
- TEST_REQUIRE(it != endIt);
- TEST_CHECK(*it == nestedFile);
- }
- } else {
- TEST_CHECK(ec);
- TEST_CHECK(ec == eacess_ec);
- TEST_CHECK(it == endIt);
- }
- }
-}
-
-
-// See llvm.org/PR35078
-TEST_CASE(test_PR35078_with_symlink_file)
-{
- using namespace fs;
- scoped_test_env env;
- const path testFiles[] = {
- env.create_dir("dir1"),
- env.create_dir("dir1/dir2"),
- env.create_file("dir1/file2"),
- env.create_dir("sym_dir"),
- env.create_dir("sym_dir/sdir1"),
- env.create_file("sym_dir/sdir1/sfile1"),
- env.create_symlink("sym_dir/sdir1/sfile1", "dir1/dir2/file1")
- };
- const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
- const path startDir = testFiles[0];
- const path nestedDir = testFiles[1];
- const path nestedFile = testFiles[2];
- const path permDeniedDir = testFiles[3];
- const path symFile = testFiles[TestFilesSize - 1];
-
- // Change the permissions so we can no longer iterate
- permissions(permDeniedDir,
- perms::group_exec|perms::owner_exec|perms::others_exec,
- perm_options::remove);
-
- const std::error_code eacess_ec =
- std::make_error_code(std::errc::permission_denied);
- std::error_code ec = GetTestEC();
-
- const recursive_directory_iterator EndIt;
-
- auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenNestedFile) {
- SeenNestedFile = false;
- auto Opts = AllowEAccess ? directory_options::skip_permission_denied
- : directory_options::none;
- if (FollowSym)
- Opts |= directory_options::follow_directory_symlink;
- recursive_directory_iterator it(startDir, Opts, ec);
- while (!ec && it != EndIt && *it != nestedDir) {
- if (*it == nestedFile)
- SeenNestedFile = true;
- it.increment(ec);
- }
- return it;
- };
-
- struct {
- bool SkipPermDenied;
- bool FollowSymlinks;
- bool ExpectSuccess;
- } TestCases[] = {
- // Passing cases
- {false, false, true}, {true, true, true}, {true, false, true},
- // Failing cases
- {false, true, false}
- };
- for (auto TC : TestCases){
- bool SeenNestedFile = false;
- recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
- TC.FollowSymlinks,
- SeenNestedFile);
- TEST_REQUIRE(!ec);
- TEST_REQUIRE(it != EndIt);
- TEST_REQUIRE(*it == nestedDir);
- ec = GetTestEC();
- it.increment(ec);
- TEST_REQUIRE(it != EndIt);
- TEST_CHECK(!ec);
- TEST_CHECK(*it == symFile);
- ec = GetTestEC();
- it.increment(ec);
- if (TC.ExpectSuccess) {
- if (!SeenNestedFile) {
- TEST_CHECK(!ec);
- TEST_REQUIRE(it != EndIt);
- TEST_CHECK(*it == nestedFile);
- ec = GetTestEC();
- it.increment(ec);
- }
- TEST_CHECK(!ec);
- TEST_CHECK(it == EndIt);
- } else {
- TEST_CHECK(ec);
- TEST_CHECK(ec == eacess_ec);
- TEST_CHECK(it == EndIt);
- }
- }
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// recursive_directory_iterator(recursive_directory_iterator&&) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_move_construct_tests)
-
-TEST_CASE(test_constructor_signature)
-{
- using D = recursive_directory_iterator;
- static_assert(std::is_nothrow_move_constructible<D>::value, "");
-}
-
-TEST_CASE(test_move_end_iterator)
-{
- const recursive_directory_iterator endIt;
- recursive_directory_iterator endIt2{};
-
- recursive_directory_iterator it(std::move(endIt2));
- TEST_CHECK(it == endIt);
- TEST_CHECK(endIt2 == endIt);
-}
-
-TEST_CASE(test_move_valid_iterator)
-{
- const path testDir = StaticEnv::Dir;
- const recursive_directory_iterator endIt{};
-
- // build 'it' up with "interesting" non-default state so we can test
- // that it gets copied. We want to get 'it' into a state such that:
- // it.options() != directory_options::none
- // it.depth() != 0
- // it.recursion_pending() != true
- const directory_options opts = directory_options::skip_permission_denied;
- recursive_directory_iterator it(testDir, opts);
- TEST_REQUIRE(it != endIt);
- while (it.depth() == 0) {
- ++it;
- TEST_REQUIRE(it != endIt);
- }
- it.disable_recursion_pending();
- TEST_CHECK(it.options() == opts);
- TEST_CHECK(it.depth() == 1);
- TEST_CHECK(it.recursion_pending() == false);
- const path entry = *it;
-
- // OPERATION UNDER TEST //
- const recursive_directory_iterator it2(std::move(it));
- // ------------------- //
-
- TEST_REQUIRE(it2 != endIt);
- TEST_CHECK(*it2 == entry);
- TEST_CHECK(it2.depth() == 1);
- TEST_CHECK(it2.recursion_pending() == false);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// recursive_directory_iterator& operator=(recursive_directory_iterator const&);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-// The filesystem specification explicitly allows for self-move on
-// the directory iterators. Turn off this warning so we can test it.
-#if defined(__clang__)
-#pragma clang diagnostic ignored "-Wself-move"
-#endif
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_move_assign_tests)
-
-recursive_directory_iterator createInterestingIterator()
- // Create an "interesting" iterator where all fields are
- // in a non-default state. The returned 'it' is in a
- // state such that:
- // it.options() == directory_options::skip_permission_denied
- // it.depth() == 1
- // it.recursion_pending() == true
-{
- const path testDir = StaticEnv::Dir;
- const recursive_directory_iterator endIt;
- recursive_directory_iterator it(testDir,
- directory_options::skip_permission_denied);
- TEST_ASSERT(it != endIt);
- while (it.depth() != 1) {
- ++it;
- TEST_ASSERT(it != endIt);
- }
- TEST_ASSERT(it.depth() == 1);
- it.disable_recursion_pending();
- return it;
-}
-
-recursive_directory_iterator createDifferentInterestingIterator()
- // Create an "interesting" iterator where all fields are
- // in a non-default state. The returned 'it' is in a
- // state such that:
- // it.options() == directory_options::follow_directory_symlink
- // it.depth() == 2
- // it.recursion_pending() == false
-{
- const path testDir = StaticEnv::Dir;
- const recursive_directory_iterator endIt;
- recursive_directory_iterator it(testDir,
- directory_options::follow_directory_symlink);
- TEST_ASSERT(it != endIt);
- while (it.depth() != 2) {
- ++it;
- TEST_ASSERT(it != endIt);
- }
- TEST_ASSERT(it.depth() == 2);
- return it;
-}
-
-
-TEST_CASE(test_assignment_signature)
-{
- using D = recursive_directory_iterator;
- static_assert(std::is_nothrow_move_assignable<D>::value, "");
-}
-
-
-TEST_CASE(test_move_to_end_iterator)
-{
- const recursive_directory_iterator endIt;
-
- recursive_directory_iterator from = createInterestingIterator();
- const recursive_directory_iterator from_copy(from);
- const path entry = *from;
-
- recursive_directory_iterator to;
- to = std::move(from);
- TEST_REQUIRE(to != endIt);
- TEST_CHECK(*to == entry);
- TEST_CHECK(to.options() == from_copy.options());
- TEST_CHECK(to.depth() == from_copy.depth());
- TEST_CHECK(to.recursion_pending() == from_copy.recursion_pending());
- TEST_CHECK(from == endIt || from == to);
-}
-
-
-TEST_CASE(test_move_from_end_iterator)
-{
- recursive_directory_iterator from;
- recursive_directory_iterator to = createInterestingIterator();
-
- to = std::move(from);
- TEST_REQUIRE(to == from);
- TEST_CHECK(to == recursive_directory_iterator{});
-}
-
-TEST_CASE(test_move_valid_iterator)
-{
- const recursive_directory_iterator endIt;
-
- recursive_directory_iterator it = createInterestingIterator();
- const recursive_directory_iterator it_copy(it);
- const path entry = *it;
-
- recursive_directory_iterator it2 = createDifferentInterestingIterator();
- const recursive_directory_iterator it2_copy(it2);
- TEST_REQUIRE(it2 != it);
- TEST_CHECK(it2.options() != it.options());
- TEST_CHECK(it2.depth() != it.depth());
- TEST_CHECK(it2.recursion_pending() != it.recursion_pending());
- TEST_CHECK(*it2 != entry);
-
- it2 = std::move(it);
- TEST_REQUIRE(it2 != it2_copy && it2 != endIt);
- TEST_CHECK(it2.options() == it_copy.options());
- TEST_CHECK(it2.depth() == it_copy.depth());
- TEST_CHECK(it2.recursion_pending() == it_copy.recursion_pending());
- TEST_CHECK(*it2 == entry);
- TEST_CHECK(it == endIt || it == it2);
-}
-
-TEST_CASE(test_returns_reference_to_self)
-{
- recursive_directory_iterator it;
- recursive_directory_iterator it2;
- recursive_directory_iterator& ref = (it2 = std::move(it));
- TEST_CHECK(&ref == &it2);
-}
-
-TEST_CASE(test_self_move)
-{
- // Create two non-equal iterators that have exactly the same state.
- recursive_directory_iterator it = createInterestingIterator();
- recursive_directory_iterator it2 = createInterestingIterator();
- TEST_CHECK(it != it2);
- TEST_CHECK(it2.options() == it.options());
- TEST_CHECK(it2.depth() == it.depth());
- TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
- TEST_CHECK(*it2 == *it);
-
- it = std::move(it);
- TEST_CHECK(it2.options() == it.options());
- TEST_CHECK(it2.depth() == it.depth());
- TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
- TEST_CHECK(*it2 == *it);
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// void pop();
-// void pop(error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_pop_tests)
-
-TEST_CASE(signature_tests)
-{
- recursive_directory_iterator it{}; ((void)it);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(it.pop());
- ASSERT_NOT_NOEXCEPT(it.pop(ec)); // may require allocation or other things
-}
-
-// NOTE: Since the order of iteration is unspecified we use a list of
-// seen files at each depth to determine the new depth after a 'pop()' operation.
-TEST_CASE(test_depth)
-{
- const recursive_directory_iterator endIt{};
-
- auto& DE0 = StaticEnv::DirIterationList;
- std::set<path> notSeenDepth0(std::begin(DE0), std::end(DE0));
-
- auto& DE1 = StaticEnv::DirIterationListDepth1;
- std::set<path> notSeenDepth1(std::begin(DE1), std::end(DE1));
-
- std::error_code ec;
- recursive_directory_iterator it(StaticEnv::Dir, ec);
- TEST_REQUIRE(it != endIt);
- TEST_CHECK(it.depth() == 0);
-
- while (it.depth() != 2) {
- if (it.depth() == 0)
- notSeenDepth0.erase(it->path());
- else
- notSeenDepth1.erase(it->path());
- ++it;
- TEST_REQUIRE(it != endIt);
- }
-
- while (true) {
- auto set_ec = std::make_error_code(std::errc::address_in_use);
- it.pop(set_ec);
- TEST_REQUIRE(!set_ec);
-
- if (it == endIt) {
- // We must have seen every entry at depth 0 and 1.
- TEST_REQUIRE(notSeenDepth0.empty() && notSeenDepth1.empty());
- break;
- }
- else if (it.depth() == 1) {
- // If we popped to depth 1 then there must be unseen entries
- // at this level.
- TEST_REQUIRE(!notSeenDepth1.empty());
- TEST_CHECK(notSeenDepth1.count(it->path()));
- notSeenDepth1.clear();
- }
- else if (it.depth() == 0) {
- // If we popped to depth 0 there must be unseen entries at this
- // level. There should also be no unseen entries at depth 1.
- TEST_REQUIRE(!notSeenDepth0.empty());
- TEST_REQUIRE(notSeenDepth1.empty());
- TEST_CHECK(notSeenDepth0.count(it->path()));
- notSeenDepth0.clear();
- }
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// bool recursion_pending() const;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_recursion_pending_tests)
-
-TEST_CASE(initial_value_test)
-{
- recursive_directory_iterator it(StaticEnv::Dir);
- TEST_REQUIRE(it.recursion_pending() == true);
-}
-
-TEST_CASE(value_after_copy_construction_and_assignment_test)
-{
- recursive_directory_iterator rec_pending_it(StaticEnv::Dir);
- recursive_directory_iterator no_rec_pending_it(StaticEnv::Dir);
- no_rec_pending_it.disable_recursion_pending();
-
- { // copy construction
- recursive_directory_iterator it(rec_pending_it);
- TEST_CHECK(it.recursion_pending() == true);
- it.disable_recursion_pending();
- TEST_REQUIRE(rec_pending_it.recursion_pending() == true);
-
- recursive_directory_iterator it2(no_rec_pending_it);
- TEST_CHECK(it2.recursion_pending() == false);
- }
- { // copy assignment
- recursive_directory_iterator it(StaticEnv::Dir);
- it.disable_recursion_pending();
- it = rec_pending_it;
- TEST_CHECK(it.recursion_pending() == true);
- it.disable_recursion_pending();
- TEST_REQUIRE(rec_pending_it.recursion_pending() == true);
-
- recursive_directory_iterator it2(StaticEnv::Dir);
- it2 = no_rec_pending_it;
- TEST_CHECK(it2.recursion_pending() == false);
- }
- TEST_CHECK(rec_pending_it.recursion_pending() == true);
- TEST_CHECK(no_rec_pending_it.recursion_pending() == false);
-}
-
-
-TEST_CASE(value_after_move_construction_and_assignment_test)
-{
- recursive_directory_iterator rec_pending_it(StaticEnv::Dir);
- recursive_directory_iterator no_rec_pending_it(StaticEnv::Dir);
- no_rec_pending_it.disable_recursion_pending();
-
- { // move construction
- recursive_directory_iterator it_cp(rec_pending_it);
- recursive_directory_iterator it(std::move(it_cp));
- TEST_CHECK(it.recursion_pending() == true);
-
- recursive_directory_iterator it_cp2(no_rec_pending_it);
- recursive_directory_iterator it2(std::move(it_cp2));
- TEST_CHECK(it2.recursion_pending() == false);
- }
- { // copy assignment
- recursive_directory_iterator it(StaticEnv::Dir);
- it.disable_recursion_pending();
- recursive_directory_iterator it_cp(rec_pending_it);
- it = std::move(it_cp);
- TEST_CHECK(it.recursion_pending() == true);
-
- recursive_directory_iterator it2(StaticEnv::Dir);
- recursive_directory_iterator it_cp2(no_rec_pending_it);
- it2 = std::move(it_cp2);
- TEST_CHECK(it2.recursion_pending() == false);
- }
- TEST_CHECK(rec_pending_it.recursion_pending() == true);
- TEST_CHECK(no_rec_pending_it.recursion_pending() == false);
-}
-
-TEST_CASE(increment_resets_value)
-{
- const recursive_directory_iterator endIt;
- {
- recursive_directory_iterator it(StaticEnv::Dir);
- it.disable_recursion_pending();
- TEST_CHECK(it.recursion_pending() == false);
- ++it;
- TEST_CHECK(it.recursion_pending() == true);
- TEST_CHECK(it.depth() == 0);
- }
- {
- recursive_directory_iterator it(StaticEnv::Dir);
- it.disable_recursion_pending();
- TEST_CHECK(it.recursion_pending() == false);
- it++;
- TEST_CHECK(it.recursion_pending() == true);
- TEST_CHECK(it.depth() == 0);
- }
- {
- recursive_directory_iterator it(StaticEnv::Dir);
- it.disable_recursion_pending();
- TEST_CHECK(it.recursion_pending() == false);
- std::error_code ec;
- it.increment(ec);
- TEST_CHECK(it.recursion_pending() == true);
- TEST_CHECK(it.depth() == 0);
- }
-}
-
-TEST_CASE(pop_does_not_reset_value)
-{
- const recursive_directory_iterator endIt;
-
- auto& DE0 = StaticEnv::DirIterationList;
- std::set<path> notSeenDepth0(std::begin(DE0), std::end(DE0));
-
- recursive_directory_iterator it(StaticEnv::Dir);
- TEST_REQUIRE(it != endIt);
-
- while (it.depth() == 0) {
- notSeenDepth0.erase(it->path());
- ++it;
- TEST_REQUIRE(it != endIt);
- }
- TEST_REQUIRE(it.depth() == 1);
- it.disable_recursion_pending();
- it.pop();
- // Since the order of iteration is unspecified the pop() could result
- // in the end iterator. When this is the case it is undefined behavior
- // to call recursion_pending().
- if (it == endIt) {
- TEST_CHECK(notSeenDepth0.empty());
-#if defined(_LIBCPP_VERSION)
- TEST_CHECK(it.recursion_pending() == false);
-#endif
- } else {
- TEST_CHECK(! notSeenDepth0.empty());
- TEST_CHECK(it.recursion_pending() == false);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class recursive_directory_iterator
-
-// recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
-// recursive_directory_iterator end(recursive_directory_iterator iter) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <set>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-#include <iostream>
-
-using namespace fs;
-
-TEST_SUITE(recursive_directory_iterator_begin_end_tests)
-
-TEST_CASE(test_function_signatures)
-{
- using D = recursive_directory_iterator;
- recursive_directory_iterator d; ((void)d);
-
- ASSERT_SAME_TYPE(decltype(begin(d)), recursive_directory_iterator);
- ASSERT_NOEXCEPT(begin(std::move(d)));
-
- ASSERT_SAME_TYPE(decltype(end(d)), recursive_directory_iterator);
- ASSERT_NOEXCEPT(end(std::move(d)));
-}
-
-TEST_CASE(test_ranged_for_loop)
-{
- const path testDir = StaticEnv::Dir;
- std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
- std::end( StaticEnv::RecDirIterationList));
-
- std::error_code ec;
- recursive_directory_iterator it(testDir, ec);
- TEST_REQUIRE(!ec);
-
- for (auto& elem : it) {
- TEST_CHECK(dir_contents.erase(elem) == 1);
- }
- TEST_CHECK(dir_contents.empty());
-}
-
-TEST_SUITE_END()
+++ /dev/null
-#ifndef TEST_BITMASK_TYPE_HPP
-#define TEST_BITMASK_TYPE_HPP
-
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-template <class EnumType, EnumType Val1, EnumType Val2,
- class UT = typename std::underlying_type<EnumType>::type,
- UT UVal1 = static_cast<UT>(Val1),
- UT UVal2 = static_cast<UT>(Val2),
- UT UZero = static_cast<UT>(0),
- EnumType Zero = static_cast<EnumType>(0)
- >
-struct check_bitmask_type {
-
- static constexpr UT dcast(EnumType e) { return static_cast<UT>(e); }
- static constexpr UT unpromote(decltype((~UZero)) promoted) { return static_cast<UT>(promoted); }
- // We need two values that are non-zero and share at least one bit.
- static_assert(Val1 != Zero && Val2 != Zero, "");
- static_assert(Val1 != Val2, "");
- static_assert((UVal1 & UVal2) == 0, "");
-
-
- static bool check()
- {
- {
- EnumType ValRef = Val1;
- ASSERT_SAME_TYPE(EnumType, decltype(Val1 & Val2));
- ASSERT_SAME_TYPE(EnumType, decltype(Val1 | Val2));
- ASSERT_SAME_TYPE(EnumType, decltype(Val1 ^ Val2));
- ASSERT_SAME_TYPE(EnumType, decltype((~Val1)));
- ASSERT_SAME_TYPE(EnumType&, decltype(ValRef &= Val2));
- ASSERT_SAME_TYPE(EnumType&, decltype(ValRef |= Val2));
- ASSERT_SAME_TYPE(EnumType&, decltype(ValRef ^= Val2));
- }
-
- static_assert((Val1 & Zero) == Zero, "");
- static_assert((Val1 & Val1) == Val1, "");
- static_assert(dcast(Val1 & Val2) == (UVal1 & UVal2), "");
-
- static_assert((Val1 | Zero) == Val1, "");
- static_assert(dcast(Val1 | Val2) == (UVal1 | UVal2), "");
-
- static_assert((Val1 ^ Zero) == Val1, "");
- static_assert(dcast(Val1 ^ Val2) == (UVal1 ^ UVal2), "");
-
- static_assert(dcast(~Zero) == unpromote(~UZero), "");
- static_assert(dcast(~Val1) == unpromote(~UVal1), "");
-
- {
- EnumType e = Val1;
- EnumType& eref = (e &= Val2);
- assert(&eref == &e);
- assert(dcast(eref) == (UVal1 & UVal2));
- }
- {
- EnumType e = Val1;
- EnumType& eref = (e |= Val2);
- assert(&eref == &e);
- assert(dcast(eref) == (UVal1 | UVal2));
- }
- {
- EnumType e = Val1;
- EnumType& eref = (e ^= Val2);
- assert(&eref == &e);
- assert(dcast(eref) == (UVal1 ^ UVal2));
- }
- return true;
- }
-};
-
-#endif // TEST_BITMASK_TYPE
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// enum class copy_options;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "check_bitmask_types.hpp"
-#include "test_macros.h"
-
-
-constexpr fs::copy_options ME(int val) { return static_cast<fs::copy_options>(val); }
-
-int main() {
- typedef fs::copy_options E;
- static_assert(std::is_enum<E>::value, "");
-
- // Check that E is a scoped enum by checking for conversions.
- typedef std::underlying_type<E>::type UT;
- static_assert(!std::is_convertible<E, UT>::value, "");
-
- static_assert(std::is_same<UT, unsigned short>::value, ""); // Implementation detail
-
- typedef check_bitmask_type<E, E::skip_existing, E::update_existing> BitmaskTester;
- assert(BitmaskTester::check());
-
- static_assert(
- E::none == ME(0),
- "Expected enumeration values do not match");
- // Option group for copy_file
- static_assert(
- E::skip_existing == ME(1) &&
- E::overwrite_existing == ME(2) &&
- E::update_existing == ME(4),
- "Expected enumeration values do not match");
- // Option group for copy on directories
- static_assert(
- E::recursive == ME(8),
- "Expected enumeration values do not match");
- // Option group for copy on symlinks
- static_assert(
- E::copy_symlinks == ME(16) &&
- E::skip_symlinks == ME(32),
- "Expected enumeration values do not match");
- // Option group for changing form of copy
- static_assert(
- E::directories_only == ME(64) &&
- E::create_symlinks == ME(128) &&
- E::create_hard_links == ME(256),
- "Expected enumeration values do not match");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// enum class directory_options;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-#include <sys/stat.h>
-
-#include "test_macros.h"
-#include "check_bitmask_types.hpp"
-
-
-constexpr fs::directory_options ME(int val) { return static_cast<fs::directory_options>(val); }
-
-int main() {
- typedef fs::directory_options E;
- static_assert(std::is_enum<E>::value, "");
-
- // Check that E is a scoped enum by checking for conversions.
- typedef std::underlying_type<E>::type UT;
- static_assert(!std::is_convertible<E, UT>::value, "");
- static_assert(std::is_same<UT, unsigned char>::value, "");
-
- typedef check_bitmask_type<E, E::follow_directory_symlink, E::skip_permission_denied> BitmaskTester;
- assert(BitmaskTester::check());
-
- static_assert(
- E::none == ME(0) &&
- E::follow_directory_symlink == ME(1) &&
- E::skip_permission_denied == ME(2),
- "Expected enumeration values do not match");
-
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// enum class file_type;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-
-constexpr fs::file_type ME(int val) { return static_cast<fs::file_type>(val); }
-
-int main() {
- typedef fs::file_type E;
- static_assert(std::is_enum<E>::value, "");
-
- // Check that E is a scoped enum by checking for conversions.
- typedef std::underlying_type<E>::type UT;
- static_assert(!std::is_convertible<E, UT>::value, "");
-
- static_assert(std::is_same<UT, signed char>::value, ""); // Implementation detail
-
- static_assert(
- E::none == ME(0) &&
- E::not_found == ME(-1) &&
- E::regular == ME(1) &&
- E::directory == ME(2) &&
- E::symlink == ME(3) &&
- E::block == ME(4) &&
- E::character == ME(5) &&
- E::fifo == ME(6) &&
- E::socket == ME(7) &&
- E::unknown == ME(8),
- "Expected enumeration values do not match");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// class path;
-// enum class format;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-
-int main() {
- typedef fs::path::format E;
- static_assert(std::is_enum<E>::value, "");
-
- // Check that E is a scoped enum by checking for conversions.
- typedef std::underlying_type<E>::type UT;
- static_assert(!std::is_convertible<E, UT>::value, "");
-
- LIBCPP_ONLY(static_assert(std::is_same<UT, unsigned char>::value, "")); // Implementation detail
-
- static_assert(
- E::auto_format != E::native_format &&
- E::auto_format != E::generic_format &&
- E::native_format != E::generic_format,
- "Expected enumeration values are not unique");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// enum class perm_options;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-#include <sys/stat.h>
-
-#include "test_macros.h"
-#include "check_bitmask_types.hpp"
-
-
-constexpr fs::perm_options ME(int val) {
- return static_cast<fs::perm_options>(val);
-}
-
-int main() {
- typedef fs::perm_options E;
- static_assert(std::is_enum<E>::value, "");
-
- // Check that E is a scoped enum by checking for conversions.
- typedef std::underlying_type<E>::type UT;
- static_assert(!std::is_convertible<E, UT>::value, "");
-
- static_assert(std::is_same<UT, unsigned char >::value, ""); // Implementation detail
-
- typedef check_bitmask_type<E, E::replace, E::nofollow> BitmaskTester;
- assert(BitmaskTester::check());
-
- static_assert(
- E::replace == ME(1) &&
- E::add == ME(2) &&
- E::remove == ME(4) &&
- E::nofollow == ME(8),
- "Expected enumeration values do not match");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// enum class perms;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-#include <sys/stat.h>
-
-#include "test_macros.h"
-#include "check_bitmask_types.hpp"
-
-
-constexpr fs::perms ME(int val) { return static_cast<fs::perms>(val); }
-
-int main() {
- typedef fs::perms E;
- static_assert(std::is_enum<E>::value, "");
-
- // Check that E is a scoped enum by checking for conversions.
- typedef std::underlying_type<E>::type UT;
- static_assert(!std::is_convertible<E, UT>::value, "");
-
- static_assert(std::is_same<UT, unsigned >::value, ""); // Implementation detail
-
- typedef check_bitmask_type<E, E::group_all, E::owner_all> BitmaskTester;
- assert(BitmaskTester::check());
-
- static_assert(
- E::none == ME(0) &&
-
- E::owner_read == ME(0400) &&
- E::owner_write == ME(0200) &&
- E::owner_exec == ME(0100) &&
- E::owner_all == ME(0700) &&
-
- E::group_read == ME(040) &&
- E::group_write == ME(020) &&
- E::group_exec == ME(010) &&
- E::group_all == ME(070) &&
-
- E::others_read == ME(04) &&
- E::others_write == ME(02) &&
- E::others_exec == ME(01) &&
- E::others_all == ME(07) &&
- E::all == ME(0777) &&
- E::set_uid == ME(04000) &&
- E::set_gid == ME(02000) &&
- E::sticky_bit == ME(01000) &&
- E::mask == ME(07777) &&
- E::unknown == ME(0xFFFF),
- "Expected enumeration values do not match");
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-int main()
-{
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// typedef TrivialClock file_time_type;
-
-#include "filesystem_include.hpp"
-#include <chrono>
-#include <type_traits>
-
-#include "test_macros.h"
-
-// system_clock is used because it meets the requirements of TrivialClock,
-// and the resolution and range of system_clock should match the operating
-// system's file time type.
-
-void test_trivial_clock() {
- using namespace fs;
- using Clock = file_time_type::clock;
- ASSERT_NOEXCEPT(Clock::now());
- ASSERT_SAME_TYPE(decltype(Clock::now()), file_time_type);
- ASSERT_SAME_TYPE(Clock::time_point, file_time_type);
- volatile auto* odr_use = &Clock::is_steady;
- ((void)odr_use);
-}
-
-void test_time_point_resolution_and_range() {
- using namespace fs;
- using Dur = file_time_type::duration;
- using Period = Dur::period;
- ASSERT_SAME_TYPE(Period, std::nano);
-}
-
-int main() {
- test_trivial_clock();
- test_time_point_resolution_and_range();
-}
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path absolute(const path& p, const path& base=current_path());
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_absolute_path_test_suite)
-
-TEST_CASE(absolute_signature_test)
-{
- const path p; ((void)p);
- std::error_code ec;
- ASSERT_NOT_NOEXCEPT(absolute(p));
- ASSERT_NOT_NOEXCEPT(absolute(p, ec));
-}
-
-
-TEST_CASE(basic_test)
-{
- const fs::path cwd = fs::current_path();
- const struct {
- std::string input;
- std::string expect;
- } TestCases [] = {
- {"", cwd / ""},
- {"foo", cwd / "foo"},
- {"foo/", cwd / "foo/"},
- {"/already_absolute", "/already_absolute"}
- };
- for (auto& TC : TestCases) {
- std::error_code ec = GetTestEC();
- const path ret = absolute(TC.input, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ret.is_absolute());
- TEST_CHECK(PathEq(ret, TC.expect));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path canonical(const path& p);
-// path canonical(const path& p, error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-struct CWDGuard {
- path OldCWD;
- CWDGuard() : OldCWD(fs::current_path()) { }
- ~CWDGuard() { fs::current_path(OldCWD); }
-
- CWDGuard(CWDGuard const&) = delete;
- CWDGuard& operator=(CWDGuard const&) = delete;
-};
-
-TEST_SUITE(filesystem_canonical_path_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(canonical(p));
- ASSERT_NOT_NOEXCEPT(canonical(p, ec));
-}
-
-// There are 4 cases is the proposal for absolute path.
-// Each scope tests one of the cases.
-TEST_CASE(test_canonical)
-{
- CWDGuard guard;
- // has_root_name() && has_root_directory()
- const path Root = StaticEnv::Root;
- const path RootName = Root.filename();
- const path DirName = StaticEnv::Dir.filename();
- const path SymlinkName = StaticEnv::SymlinkToFile.filename();
- struct TestCase {
- path p;
- path expect;
- path base;
- TestCase(path p1, path e, path b = StaticEnv::Root)
- : p(p1), expect(e), base(b) {}
- };
- const TestCase testCases[] = {
- { ".", Root, Root},
- { DirName / ".." / "." / DirName, StaticEnv::Dir, Root},
- { StaticEnv::Dir2 / "..", StaticEnv::Dir },
- { StaticEnv::Dir3 / "../..", StaticEnv::Dir },
- { StaticEnv::Dir / ".", StaticEnv::Dir },
- { Root / "." / DirName / ".." / DirName, StaticEnv::Dir},
- { path("..") / "." / RootName / DirName / ".." / DirName, StaticEnv::Dir, Root},
- { StaticEnv::SymlinkToFile, StaticEnv::File },
- { SymlinkName, StaticEnv::File, StaticEnv::Root}
- };
- for (auto& TC : testCases) {
- std::error_code ec = GetTestEC();
- fs::current_path(TC.base);
- const path ret = canonical(TC.p, ec);
- TEST_REQUIRE(!ec);
- const path ret2 = canonical(TC.p);
- TEST_CHECK(PathEq(ret, TC.expect));
- TEST_CHECK(PathEq(ret, ret2));
- TEST_CHECK(ret.is_absolute());
- }
-}
-
-TEST_CASE(test_dne_path)
-{
- std::error_code ec = GetTestEC();
- {
- const path ret = canonical(StaticEnv::DNE, ec);
- TEST_CHECK(ec != GetTestEC());
- TEST_REQUIRE(ec);
- TEST_CHECK(ret == path{});
- }
- {
- TEST_CHECK_THROW(filesystem_error, canonical(StaticEnv::DNE));
- }
-}
-
-TEST_CASE(test_exception_contains_paths)
-{
-#ifndef TEST_HAS_NO_EXCEPTIONS
- CWDGuard guard;
- const path p = "blabla/dne";
- try {
- canonical(p);
- TEST_REQUIRE(false);
- } catch (filesystem_error const& err) {
- TEST_CHECK(err.path1() == p);
- // libc++ provides the current path as the second path in the exception
- LIBCPP_ONLY(TEST_CHECK(err.path2() == current_path()));
- }
- fs::current_path(StaticEnv::Dir);
- try {
- canonical(p);
- TEST_REQUIRE(false);
- } catch (filesystem_error const& err) {
- TEST_CHECK(err.path1() == p);
- LIBCPP_ONLY(TEST_CHECK(err.path2() == StaticEnv::Dir));
- }
-#endif
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void copy(const path& from, const path& to);
-// void copy(const path& from, const path& to, error_code& ec);
-// void copy(const path& from, const path& to, copy_options options);
-// void copy(const path& from, const path& to, copy_options options,
-// error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cstddef>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-using CO = fs::copy_options;
-
-TEST_SUITE(filesystem_copy_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- const copy_options opts{}; ((void)opts);
- ASSERT_NOT_NOEXCEPT(fs::copy(p, p));
- ASSERT_NOT_NOEXCEPT(fs::copy(p, p, ec));
- ASSERT_NOT_NOEXCEPT(copy(p, p, opts));
- ASSERT_NOT_NOEXCEPT(copy(p, p, opts, ec));
-}
-
-// There are 4 cases is the proposal for absolute path.
-// Each scope tests one of the cases.
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::copy(f, t);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == t
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)t); ((void)ec);
- return true;
-#endif
- };
-
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path dir = env.create_dir("dir");
- const path fifo = env.create_fifo("fifo");
- TEST_REQUIRE(is_other(fifo));
-
- const auto test_ec = GetTestEC();
-
- // !exists(f)
- {
- std::error_code ec = test_ec;
- const path f = StaticEnv::DNE;
- const path t = env.test_root;
- fs::copy(f, t, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(ec != test_ec);
- TEST_CHECK(checkThrow(f, t, ec));
- }
- { // equivalent(f, t) == true
- std::error_code ec = test_ec;
- fs::copy(file, file, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(ec != test_ec);
- TEST_CHECK(checkThrow(file, file, ec));
- }
- { // is_directory(from) && is_file(to)
- std::error_code ec = test_ec;
- fs::copy(dir, file, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(ec != test_ec);
- TEST_CHECK(checkThrow(dir, file, ec));
- }
- { // is_other(from)
- std::error_code ec = test_ec;
- fs::copy(fifo, dir, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(ec != test_ec);
- TEST_CHECK(checkThrow(fifo, dir, ec));
- }
- { // is_other(to)
- std::error_code ec = test_ec;
- fs::copy(file, fifo, ec);
- TEST_REQUIRE(ec);
- TEST_REQUIRE(ec != test_ec);
- TEST_CHECK(checkThrow(file, fifo, ec));
- }
-}
-
-TEST_CASE(from_is_symlink)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path symlink = env.create_symlink(file, "sym");
- const path dne = env.make_env_path("dne");
-
- { // skip symlinks
- std::error_code ec = GetTestEC();
- fs::copy(symlink, dne, copy_options::skip_symlinks, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(dne));
- }
- {
- const path dest = env.make_env_path("dest");
- std::error_code ec = GetTestEC();
- fs::copy(symlink, dest, copy_options::copy_symlinks, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(exists(dest));
- TEST_CHECK(is_symlink(dest));
- }
- { // copy symlink but target exists
- std::error_code ec = GetTestEC();
- fs::copy(symlink, file, copy_options::copy_symlinks, ec);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
- }
- { // create symlinks but target exists
- std::error_code ec = GetTestEC();
- fs::copy(symlink, file, copy_options::create_symlinks, ec);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
- }
-}
-
-TEST_CASE(from_is_regular_file)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
- { // skip copy because of directory
- const path dest = env.make_env_path("dest1");
- std::error_code ec = GetTestEC();
- fs::copy(file, dest, CO::directories_only, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(dest));
- }
- { // create symlink to file
- const path dest = env.make_env_path("sym");
- std::error_code ec = GetTestEC();
- fs::copy(file, dest, CO::create_symlinks, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(is_symlink(dest));
- TEST_CHECK(equivalent(file, canonical(dest)));
- }
- { // create hard link to file
- const path dest = env.make_env_path("hardlink");
- TEST_CHECK(hard_link_count(file) == 1);
- std::error_code ec = GetTestEC();
- fs::copy(file, dest, CO::create_hard_links, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(exists(dest));
- TEST_CHECK(hard_link_count(file) == 2);
- }
- { // is_directory(t)
- const path dest_dir = env.create_dir("dest_dir");
- const path expect_dest = dest_dir / file.filename();
- std::error_code ec = GetTestEC();
- fs::copy(file, dest_dir, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(is_regular_file(expect_dest));
- }
- { // otherwise copy_file(from, to, ...)
- const path dest = env.make_env_path("file_copy");
- std::error_code ec = GetTestEC();
- fs::copy(file, dest, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(is_regular_file(dest));
- }
-}
-
-TEST_CASE(from_is_directory)
-{
- struct FileInfo {
- path filename;
- std::size_t size;
- };
- const FileInfo files[] = {
- {"file1", 0},
- {"file2", 42},
- {"file3", 300}
- };
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path nested_dir_name = "dir2";
- const path nested_dir = env.create_dir("dir/dir2");
-
- for (auto& FI : files) {
- env.create_file(dir / FI.filename, FI.size);
- env.create_file(nested_dir / FI.filename, FI.size);
- }
- { // test for non-existent directory
- const path dest = env.make_env_path("dest_dir1");
- std::error_code ec = GetTestEC();
- fs::copy(dir, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_directory(dest));
- for (auto& FI : files) {
- path created = dest / FI.filename;
- TEST_CHECK(is_regular_file(created));
- TEST_CHECK(file_size(created) == FI.size);
- }
- TEST_CHECK(!is_directory(dest / nested_dir_name));
- }
- { // test for existing directory
- const path dest = env.create_dir("dest_dir2");
- std::error_code ec = GetTestEC();
- fs::copy(dir, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_directory(dest));
- for (auto& FI : files) {
- path created = dest / FI.filename;
- TEST_CHECK(is_regular_file(created));
- TEST_CHECK(file_size(created) == FI.size);
- }
- TEST_CHECK(!is_directory(dest / nested_dir_name));
- }
- { // test recursive copy
- const path dest = env.make_env_path("dest_dir3");
- std::error_code ec = GetTestEC();
- fs::copy(dir, dest, CO::recursive, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_directory(dest));
- const path nested_dest = dest / nested_dir_name;
- TEST_REQUIRE(is_directory(nested_dest));
- for (auto& FI : files) {
- path created = dest / FI.filename;
- path nested_created = nested_dest / FI.filename;
- TEST_CHECK(is_regular_file(created));
- TEST_CHECK(file_size(created) == FI.size);
- TEST_CHECK(is_regular_file(nested_created));
- TEST_CHECK(file_size(nested_created) == FI.size);
- }
- }
-}
-
-TEST_CASE(test_copy_symlinks_to_symlink_dir)
-{
- scoped_test_env env;
- const path file1 = env.create_file("file1", 42);
- const path file2 = env.create_file("file2", 101);
- const path file2_sym = env.create_symlink(file2, "file2_sym");
- const path dir = env.create_dir("dir");
- const path dir_sym = env.create_symlink(dir, "dir_sym");
- {
- std::error_code ec = GetTestEC();
- fs::copy(file1, dir_sym, copy_options::copy_symlinks, ec);
- TEST_CHECK(!ec);
- const path dest = env.make_env_path("dir/file1");
- TEST_CHECK(exists(dest));
- TEST_CHECK(!is_symlink(dest));
- TEST_CHECK(file_size(dest) == 42);
- }
-}
-
-
-TEST_CASE(test_dir_create_symlink)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir1");
- const path dest = env.make_env_path("dne");
- {
- std::error_code ec = GetTestEC();
- fs::copy(dir, dest, copy_options::create_symlinks, ec);
- TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory));
- TEST_CHECK(!exists(dest));
- TEST_CHECK(!is_symlink(dest));
- }
- {
- std::error_code ec = GetTestEC();
- fs::copy(dir, dest, copy_options::create_symlinks|copy_options::recursive, ec);
- TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory));
- TEST_CHECK(!exists(dest));
- TEST_CHECK(!is_symlink(dest));
- }
-}
-
-TEST_CASE(test_otherwise_no_effects_clause)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir1");
- { // skip copy because of directory
- const path dest = env.make_env_path("dest1");
- std::error_code ec;
- fs::copy(dir, dest, CO::directories_only, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(dest));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool copy_file(const path& from, const path& to);
-// bool copy_file(const path& from, const path& to, error_code& ec) noexcept;
-// bool copy_file(const path& from, const path& to, copy_options options);
-// bool copy_file(const path& from, const path& to, copy_options options,
-// error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <chrono>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-#include <iostream>
-
-using namespace fs;
-
-using CO = fs::copy_options;
-
-TEST_SUITE(filesystem_copy_file_test_suite)
-
-TEST_CASE(test_signatures) {
- const path p;
- ((void)p);
- const copy_options opts{};
- ((void)opts);
- std::error_code ec;
- ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool);
- ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool);
- ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool);
- ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool);
- ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p));
- ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts));
- ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec));
- ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec));
-}
-
-TEST_CASE(test_error_reporting) {
-
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path file2 = env.create_file("file2", 55);
- const path non_regular_file = env.create_fifo("non_reg");
- const path dne = env.make_env_path("dne");
-
- { // exists(to) && equivalent(to, from)
- std::error_code ec;
- TEST_CHECK(fs::copy_file(file, file, copy_options::overwrite_existing,
- ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::file_exists));
- ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
-
- }
- { // exists(to) && !(skip_existing | overwrite_existing | update_existing)
- std::error_code ec;
- TEST_CHECK(fs::copy_file(file, file2, ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::file_exists));
- ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
-
- }
-}
-
-TEST_CASE(non_regular_file_test) {
- scoped_test_env env;
- const path fifo = env.create_fifo("fifo");
- const path dest = env.make_env_path("dest");
- const path file = env.create_file("file", 42);
-
- {
- std::error_code ec = GetTestEC();
- TEST_REQUIRE(fs::copy_file(fifo, dest, ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::not_supported));
- TEST_CHECK(!exists(dest));
- }
- {
- std::error_code ec = GetTestEC();
- TEST_REQUIRE(fs::copy_file(file, fifo, copy_options::overwrite_existing,
- ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::not_supported));
- TEST_CHECK(is_fifo(fifo));
- }
-
-}
-
-TEST_CASE(test_attributes_get_copied) {
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path dest = env.make_env_path("file2");
- auto st = status(file);
- perms new_perms = perms::owner_read;
- permissions(file, new_perms);
- std::error_code ec = GetTestEC();
- TEST_REQUIRE(fs::copy_file(file, dest, ec) == true);
- TEST_CHECK(!ec);
- auto new_st = status(dest);
- TEST_CHECK(new_st.permissions() == new_perms);
-}
-
-TEST_CASE(copy_dir_test) {
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path dest = env.create_dir("dir1");
- std::error_code ec = GetTestEC();
- TEST_CHECK(fs::copy_file(file, dest, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
- ec = GetTestEC();
- TEST_CHECK(fs::copy_file(dest, file, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
-}
-
-TEST_CASE(copy_file) {
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
-
- { // !exists(to)
- const path dest = env.make_env_path("dest1");
- std::error_code ec = GetTestEC();
-
- TEST_REQUIRE(fs::copy_file(file, dest, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(dest) == 42);
- }
- { // exists(to) && overwrite_existing
- const path dest = env.create_file("dest2", 55);
- permissions(dest, perms::all);
- permissions(file,
- perms::group_write | perms::owner_write | perms::others_write,
- perm_options::remove);
-
- std::error_code ec = GetTestEC();
- TEST_REQUIRE(fs::copy_file(file, dest, copy_options::overwrite_existing,
- ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(dest) == 42);
- TEST_CHECK(status(dest).permissions() == status(file).permissions());
- }
- { // exists(to) && update_existing
- using Sec = std::chrono::seconds;
- const path older = env.create_file("older_file", 1);
-
- SleepFor(Sec(2));
- const path from = env.create_file("update_from", 55);
-
- SleepFor(Sec(2));
- const path newer = env.create_file("newer_file", 2);
-
- std::error_code ec = GetTestEC();
- TEST_REQUIRE(
- fs::copy_file(from, older, copy_options::update_existing, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(older) == 55);
-
- TEST_REQUIRE(
- fs::copy_file(from, newer, copy_options::update_existing, ec) == false);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(newer) == 2);
- }
- { // skip_existing
- const path file2 = env.create_file("file2", 55);
- std::error_code ec = GetTestEC();
- TEST_REQUIRE(fs::copy_file(file, file2, copy_options::skip_existing, ec) ==
- false);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(file2) == 55);
- }
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-// REQUIRES: long_tests
-
-// <experimental/filesystem>
-
-// bool copy_file(const path& from, const path& to);
-// bool copy_file(const path& from, const path& to, error_code& ec) noexcept;
-// bool copy_file(const path& from, const path& to, copy_options options);
-// bool copy_file(const path& from, const path& to, copy_options options,
-// error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <chrono>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_copy_file_test_suite)
-
-static std::string random_hex_chars(uintmax_t size) {
- std::string data;
- data.reserve(size);
- for (uintmax_t I = 0; I < size; ++I)
- data.push_back(random_utils::random_hex_char());
- return data;
-}
-
-// This test is intended to test 'sendfile's 2gb limit for a single call, and
-// to ensure that libc++ correctly copies files larger than that limit.
-// However it requires allocating ~5GB of filesystem space. This might not
-// be acceptable on all systems.
-TEST_CASE(large_file) {
- using namespace fs;
- constexpr uintmax_t sendfile_size_limit = 2147479552ull;
- constexpr uintmax_t additional_size = 1024;
- constexpr uintmax_t test_file_size = sendfile_size_limit + additional_size;
- static_assert(test_file_size > sendfile_size_limit, "");
-
- scoped_test_env env;
-
- // Check that we have more than sufficient room to create the files needed
- // to perform the test.
- if (space(env.test_root).available < 3 * test_file_size) {
- TEST_UNSUPPORTED();
- }
-
- // Use python to create a file right at the size limit.
- const path file = env.create_file("source", sendfile_size_limit);
- // Create some random data that looks different than the data before the
- // size limit.
- const std::string additional_data = random_hex_chars(additional_size);
- // Append this known data to the end of the source file.
- {
- std::ofstream outf(file.native(), std::ios_base::app);
- TEST_REQUIRE(outf.good());
- outf << additional_data;
- TEST_REQUIRE(outf);
- }
- TEST_REQUIRE(file_size(file) == test_file_size);
- const path dest = env.make_env_path("dest");
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(copy_file(file, dest, ec));
- TEST_CHECK(!ec);
-
- TEST_REQUIRE(is_regular_file(dest));
- TEST_CHECK(file_size(dest) == test_file_size);
-
- // Read the data from the end of the destination file, and ensure it matches
- // the data at the end of the source file.
- std::string out_data;
- out_data.reserve(additional_size);
- {
- std::ifstream dest_file(dest.native());
- TEST_REQUIRE(dest_file);
- dest_file.seekg(sendfile_size_limit);
- TEST_REQUIRE(dest_file);
- dest_file >> out_data;
- TEST_CHECK(dest_file.eof());
- }
- TEST_CHECK(out_data.size() == additional_data.size());
- TEST_CHECK(out_data == additional_data);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void copy_symlink(const path& existing_symlink, const path& new_symlink);
-// void copy_symlink(const path& existing_symlink, const path& new_symlink,
-// error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_copy_symlink_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(fs::copy_symlink(p, p));
- ASSERT_NOEXCEPT(fs::copy_symlink(p, p, ec));
-}
-
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::copy_symlink(f, t);
- return true;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)t); ((void)ec);
- return true;
-#endif
- };
-
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path file2 = env.create_file("file2", 55);
- const path sym = env.create_symlink(file, "sym");
- const path dir = env.create_dir("dir");
- const path dne = env.make_env_path("dne");
- { // from is a file, not a symlink
- std::error_code ec;
- fs::copy_symlink(file, dne, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(checkThrow(file, dne, ec));
- }
- { // from is a file, not a symlink
- std::error_code ec;
- fs::copy_symlink(dir, dne, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(checkThrow(dir, dne, ec));
- }
- { // destination exists
- std::error_code ec;
- fs::copy_symlink(sym, file2, ec);
- TEST_REQUIRE(ec);
- }
-}
-
-TEST_CASE(copy_symlink_basic)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dir_sym = env.create_symlink(dir, "dir_sym");
- const path file = env.create_file("file", 42);
- const path file_sym = env.create_symlink(file, "file_sym");
- { // test for directory symlinks
- const path dest = env.make_env_path("dest1");
- std::error_code ec;
- fs::copy_symlink(dir_sym, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_symlink(dest));
- TEST_CHECK(equivalent(dest, dir));
- }
- { // test for file symlinks
- const path dest = env.make_env_path("dest2");
- std::error_code ec;
- fs::copy_symlink(file_sym, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_symlink(dest));
- TEST_CHECK(equivalent(dest, file));
- }
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool create_directories(const path& p);
-// bool create_directories(const path& p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_create_directories_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::create_directories(p)), bool);
- ASSERT_SAME_TYPE(decltype(fs::create_directories(p, ec)), bool);
- ASSERT_NOT_NOEXCEPT(fs::create_directories(p));
- ASSERT_NOT_NOEXCEPT(fs::create_directories(p, ec));
-}
-
-TEST_CASE(create_existing_directory)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir1");
- std::error_code ec;
- TEST_CHECK(fs::create_directories(dir, ec) == false);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(dir));
-}
-
-TEST_CASE(create_directory_one_level)
-{
- scoped_test_env env;
- const path dir = env.make_env_path("dir1");
- std::error_code ec;
- TEST_CHECK(fs::create_directories(dir, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(dir));
-}
-
-TEST_CASE(create_directories_multi_level)
-{
- scoped_test_env env;
- const path dir = env.make_env_path("dir1/dir2/dir3");
- std::error_code ec;
- TEST_CHECK(fs::create_directories(dir, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(dir));
-}
-
-TEST_CASE(create_directory_symlinks) {
- scoped_test_env env;
- const path root = env.create_dir("dir");
- const path sym_dest_dead = env.make_env_path("dead");
- const path dead_sym = env.create_symlink(sym_dest_dead, "dir/sym_dir");
- const path target = env.make_env_path("dir/sym_dir/foo");
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(create_directories(target, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(!exists(sym_dest_dead));
- TEST_CHECK(!exists(dead_sym));
- }
-}
-
-
-TEST_CASE(create_directory_through_symlinks) {
- scoped_test_env env;
- const path root = env.create_dir("dir");
- const path sym_dir = env.create_symlink(root, "sym_dir");
- const path target = env.make_env_path("sym_dir/foo");
- const path resolved_target = env.make_env_path("dir/foo");
- TEST_REQUIRE(is_directory(sym_dir));
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(create_directories(target, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(target));
- TEST_CHECK(is_directory(resolved_target));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool create_directory(const path& p);
-// bool create_directory(const path& p, error_code& ec) noexcept;
-// bool create_directory(const path& p, const path& attr);
-// bool create_directory(const path& p, const path& attr, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-using namespace fs;
-
-fs::perms read_umask() {
- mode_t old_mask = umask(0);
- umask(old_mask); // reset the mask to the old value.
- return static_cast<fs::perms>(old_mask);
-}
-
-TEST_SUITE(filesystem_create_directory_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::create_directory(p)), bool);
- ASSERT_SAME_TYPE(decltype(fs::create_directory(p, ec)), bool);
- ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p)), bool);
- ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p, ec)), bool);
- ASSERT_NOT_NOEXCEPT(fs::create_directory(p));
- ASSERT_NOEXCEPT(fs::create_directory(p, ec));
- ASSERT_NOT_NOEXCEPT(fs::create_directory(p, p));
- ASSERT_NOEXCEPT(fs::create_directory(p, p, ec));
-}
-
-
-TEST_CASE(create_existing_directory)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir1");
- std::error_code ec;
- TEST_CHECK(fs::create_directory(dir, ec) == false);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(dir));
- // Test throwing version
- TEST_CHECK(fs::create_directory(dir) == false);
-}
-
-TEST_CASE(create_directory_one_level)
-{
- scoped_test_env env;
- const path dir = env.make_env_path("dir1");
- std::error_code ec;
- TEST_CHECK(fs::create_directory(dir, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(dir));
-
- auto st = status(dir);
- const perms expect_perms = perms::all & ~(read_umask());
- TEST_CHECK((st.permissions() & perms::all) == expect_perms);
-}
-
-TEST_CASE(create_directory_multi_level)
-{
- scoped_test_env env;
- const path dir = env.make_env_path("dir1/dir2");
- const path dir1 = env.make_env_path("dir1");
- std::error_code ec;
- TEST_CHECK(fs::create_directory(dir, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(!is_directory(dir));
- TEST_CHECK(!is_directory(dir1));
-}
-
-TEST_CASE(dest_is_file)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- std::error_code ec = GetTestEC();
- TEST_CHECK(fs::create_directory(file, ec) == false);
- TEST_CHECK(!ec);
- TEST_CHECK(is_regular_file(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool create_directory(const path& p, const path& attr);
-// bool create_directory(const path& p, const path& attr, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_create_directory_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p)), bool);
- ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p, ec)), bool);
- ASSERT_NOT_NOEXCEPT(fs::create_directory(p, p));
- ASSERT_NOEXCEPT(fs::create_directory(p, p, ec));
-}
-
-TEST_CASE(create_existing_directory)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir1");
- const path dir2 = env.create_dir("dir2");
-
- const perms orig_p = status(dir).permissions();
- permissions(dir2, perms::none);
-
- std::error_code ec;
- TEST_CHECK(fs::create_directory(dir, dir2, ec) == false);
- TEST_CHECK(!ec);
-
- // Check that the permissions were unchanged
- TEST_CHECK(orig_p == status(dir).permissions());
-
- // Test throwing version
- TEST_CHECK(fs::create_directory(dir, dir2) == false);
-}
-
-TEST_CASE(create_directory_one_level)
-{
- scoped_test_env env;
- // Remove setgid which mkdir would inherit
- permissions(env.test_root, perms::set_gid, perm_options::remove);
-
- const path dir = env.make_env_path("dir1");
- const path attr_dir = env.create_dir("dir2");
- permissions(attr_dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == true);
- TEST_CHECK(!ec);
- TEST_CHECK(is_directory(dir));
-
- // Check that the new directory has the same permissions as attr_dir
- auto st = status(dir);
- TEST_CHECK(st.permissions() == perms::none);
-}
-
-TEST_CASE(create_directory_multi_level)
-{
- scoped_test_env env;
- const path dir = env.make_env_path("dir1/dir2");
- const path dir1 = env.make_env_path("dir1");
- const path attr_dir = env.create_dir("attr_dir");
- std::error_code ec = GetTestEC();
- TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
- TEST_CHECK(!is_directory(dir));
- TEST_CHECK(!is_directory(dir1));
-}
-
-TEST_CASE(dest_is_file)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path attr_dir = env.create_dir("attr_dir");
- std::error_code ec = GetTestEC();
- TEST_CHECK(fs::create_directory(file, attr_dir, ec) == false);
- TEST_CHECK(!ec);
- TEST_CHECK(is_regular_file(file));
-}
-
-TEST_CASE(attr_dir_is_invalid) {
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path dest = env.make_env_path("dir");
- const path dne = env.make_env_path("dne");
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(create_directory(dest, file, ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::not_a_directory));
- }
- TEST_REQUIRE(!exists(dest));
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(create_directory(dest, dne, ec) == false);
- TEST_CHECK(ErrorIs(ec, std::errc::not_a_directory));
- }
-}
-
-TEST_CASE(dest_is_symlink) {
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path sym = env.create_symlink("dne_sym", "dne_sym_name");
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(create_directory(sym, dir, ec) == false);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void create_directory_symlink(const path& existing_symlink, const path& new_symlink);
-// void create_directory_symlink(const path& existing_symlink, const path& new_symlink,
-// error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_create_directory_symlink_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(fs::create_directory_symlink(p, p));
- ASSERT_NOEXCEPT(fs::create_directory_symlink(p, p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path file2 = env.create_file("file2", 55);
- const path sym = env.create_symlink(file, "sym");
- { // destination exists
- std::error_code ec;
- fs::create_directory_symlink(sym, file2, ec);
- TEST_REQUIRE(ec);
- }
-}
-
-TEST_CASE(create_directory_symlink_basic)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dir_sym = env.create_symlink(dir, "dir_sym");
-
- const path dest = env.make_env_path("dest1");
- std::error_code ec;
- fs::create_directory_symlink(dir_sym, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_symlink(dest));
- TEST_CHECK(equivalent(dest, dir));
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void create_hard_link(const path& existing_symlink, const path& new_symlink);
-// void create_hard_link(const path& existing_symlink, const path& new_symlink,
-// error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_create_hard_link_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(fs::create_hard_link(p, p));
- ASSERT_NOEXCEPT(fs::create_hard_link(p, p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path file2 = env.create_file("file2", 55);
- const path sym = env.create_symlink(file, "sym");
- { // destination exists
- std::error_code ec;
- fs::create_hard_link(sym, file2, ec);
- TEST_REQUIRE(ec);
- }
-}
-
-TEST_CASE(create_file_hard_link)
-{
- scoped_test_env env;
- const path file = env.create_file("file");
- const path dest = env.make_env_path("dest1");
- std::error_code ec;
- TEST_CHECK(hard_link_count(file) == 1);
- fs::create_hard_link(file, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(exists(dest));
- TEST_CHECK(equivalent(dest, file));
- TEST_CHECK(hard_link_count(file) == 2);
-}
-
-TEST_CASE(create_directory_hard_link_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dest = env.make_env_path("dest2");
- std::error_code ec;
-
- fs::create_hard_link(dir, dest, ec);
- TEST_REQUIRE(ec);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void create_symlink(const path& existing_symlink, const path& new_symlink);
-// void create_symlink(const path& existing_symlink, const path& new_symlink,
-// error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_create_symlink_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(fs::create_symlink(p, p));
- ASSERT_NOEXCEPT(fs::create_symlink(p, p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path file2 = env.create_file("file2", 55);
- const path sym = env.create_symlink(file, "sym");
- { // destination exists
- std::error_code ec;
- fs::create_symlink(sym, file2, ec);
- TEST_REQUIRE(ec);
- }
-}
-
-TEST_CASE(create_symlink_basic)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path file_sym = env.create_symlink(file, "file_sym");
- const path dir = env.create_dir("dir");
- const path dir_sym = env.create_symlink(dir, "dir_sym");
- {
- const path dest = env.make_env_path("dest1");
- std::error_code ec;
- fs::create_symlink(file_sym, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_symlink(dest));
- TEST_CHECK(equivalent(dest, file));
- }
- {
- const path dest = env.make_env_path("dest2");
- std::error_code ec;
- fs::create_symlink(dir_sym, dest, ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(is_symlink(dest));
- TEST_CHECK(equivalent(dest, dir));
- }
-}
-
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path current_path();
-// path current_path(error_code& ec);
-// void current_path(path const&);
-// void current_path(path const&, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_current_path_path_test_suite)
-
-TEST_CASE(current_path_signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(current_path());
- ASSERT_NOT_NOEXCEPT(current_path(ec));
- ASSERT_NOT_NOEXCEPT(current_path(p));
- ASSERT_NOEXCEPT(current_path(p, ec));
-}
-
-TEST_CASE(current_path_test)
-{
- std::error_code ec;
- const path p = current_path(ec);
- TEST_REQUIRE(!ec);
- TEST_CHECK(p.is_absolute());
- TEST_CHECK(is_directory(p));
-
- const path p2 = current_path();
- TEST_CHECK(p2 == p);
-}
-
-TEST_CASE(current_path_after_change_test)
-{
- const path new_path = StaticEnv::Dir;
- current_path(new_path);
- TEST_CHECK(current_path() == new_path);
-}
-
-TEST_CASE(current_path_is_file_test)
-{
- const path p = StaticEnv::File;
- std::error_code ec;
- const path old_p = current_path();
- current_path(p, ec);
- TEST_CHECK(ec);
- TEST_CHECK(old_p == current_path());
-}
-
-TEST_CASE(set_to_non_absolute_path)
-{
- const path base = StaticEnv::Dir;
- current_path(base);
- const path p = StaticEnv::Dir2.filename();
- std::error_code ec;
- current_path(p, ec);
- TEST_CHECK(!ec);
- const path new_cwd = current_path();
- TEST_CHECK(new_cwd == StaticEnv::Dir2);
- TEST_CHECK(new_cwd.is_absolute());
-}
-
-TEST_CASE(set_to_empty)
-{
- const path p = "";
- std::error_code ec;
- const path old_p = current_path();
- current_path(p, ec);
- TEST_CHECK(ec);
- TEST_CHECK(old_p == current_path());
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool equivalent(path const& lhs, path const& rhs);
-// bool equivalent(path const& lhs, path const& rhs, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(equivalent_test_suite)
-
-TEST_CASE(signature_test) {
- const path p;
- ((void)p);
- std::error_code ec;
- ((void)ec);
- ASSERT_NOEXCEPT(equivalent(p, p, ec));
- ASSERT_NOT_NOEXCEPT(equivalent(p, p));
-}
-
-TEST_CASE(equivalent_test) {
- struct TestCase {
- path lhs;
- path rhs;
- bool expect;
- };
- const TestCase testCases[] = {
- {StaticEnv::Dir, StaticEnv::Dir, true},
- {StaticEnv::File, StaticEnv::Dir, false},
- {StaticEnv::Dir, StaticEnv::SymlinkToDir, true},
- {StaticEnv::Dir, StaticEnv::SymlinkToFile, false},
- {StaticEnv::File, StaticEnv::File, true},
- {StaticEnv::File, StaticEnv::SymlinkToFile, true},
- };
- for (auto& TC : testCases) {
- std::error_code ec;
- TEST_CHECK(equivalent(TC.lhs, TC.rhs, ec) == TC.expect);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(equivalent_reports_error_if_input_dne) {
- const path E = StaticEnv::File;
- const path DNE = StaticEnv::DNE;
- { // Test that an error is reported when either of the paths don't exist
- std::error_code ec = GetTestEC();
- TEST_CHECK(equivalent(E, DNE, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
- }
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(equivalent(DNE, E, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
- }
- {
- TEST_CHECK_THROW(filesystem_error, equivalent(DNE, E));
- TEST_CHECK_THROW(filesystem_error, equivalent(E, DNE));
- }
- { // Test that an exception is thrown if both paths do not exist.
- TEST_CHECK_THROW(filesystem_error, equivalent(DNE, DNE));
- }
- {
- std::error_code ec = GetTestEC();
- TEST_CHECK(equivalent(DNE, DNE, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
- }
-}
-
-TEST_CASE(equivalent_hardlink_succeeds) {
- scoped_test_env env;
- path const file = env.create_file("file", 42);
- const path hl1 = env.create_hardlink(file, "hl1");
- const path hl2 = env.create_hardlink(file, "hl2");
- TEST_CHECK(equivalent(file, hl1));
- TEST_CHECK(equivalent(file, hl2));
- TEST_CHECK(equivalent(hl1, hl2));
-}
-
-TEST_CASE(equivalent_is_other_succeeds) {
- scoped_test_env env;
- path const file = env.create_file("file", 42);
- const path fifo1 = env.create_fifo("fifo1");
- const path fifo2 = env.create_fifo("fifo2");
- // Required to test behavior for inputs where is_other(p) is true.
- TEST_REQUIRE(is_other(fifo1));
- TEST_CHECK(!equivalent(file, fifo1));
- TEST_CHECK(!equivalent(fifo2, file));
- TEST_CHECK(!equivalent(fifo1, fifo2));
- TEST_CHECK(equivalent(fifo1, fifo1));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool exists(file_status s) noexcept
-// bool exists(path const& p);
-// bool exists(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(exists_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(exists(s));
- ASSERT_NOEXCEPT(exists(p, ec));
- ASSERT_NOT_NOEXCEPT(exists(p));
-}
-
-TEST_CASE(exists_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, true},
- {file_type::directory, true},
- {file_type::symlink, true},
- {file_type::block, true},
- {file_type::character, true},
- {file_type::fifo, true},
- {file_type::socket, true},
- {file_type::unknown, true}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(exists(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(exists(p) == false);
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(exists(p, ec) == false);
- TEST_CHECK(!ec);
-}
-
-TEST_CASE(test_exists_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(exists(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, exists(file));
-}
-
-TEST_CASE(test_name_too_long) {
- std::string long_name(2500, 'a');
- const path file(long_name);
-
- std::error_code ec;
- TEST_CHECK(exists(file, ec) == false);
- TEST_CHECK(ec);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// uintmax_t file_size(const path& p);
-// uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(file_size_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(file_size(p)), uintmax_t);
- ASSERT_SAME_TYPE(decltype(file_size(p, ec)), uintmax_t);
- ASSERT_NOT_NOEXCEPT(file_size(p));
- ASSERT_NOEXCEPT(file_size(p, ec));
-}
-
-TEST_CASE(file_size_empty_test)
-{
- const path p = StaticEnv::EmptyFile;
- TEST_CHECK(file_size(p) == 0);
- std::error_code ec;
- TEST_CHECK(file_size(p, ec) == 0);
-}
-
-TEST_CASE(file_size_non_empty)
-{
- scoped_test_env env;
- const path p = env.create_file("file", 42);
- TEST_CHECK(file_size(p) == 42);
- std::error_code ec;
- TEST_CHECK(file_size(p, ec) == 42);
-}
-
-TEST_CASE(symlink_test_case)
-{
- const path p = StaticEnv::File;
- const path p2 = StaticEnv::SymlinkToFile;
- TEST_CHECK(file_size(p) == file_size(p2));
-}
-
-TEST_CASE(file_size_error_cases)
-{
- struct {
- path p;
- std::errc expected_err;
- } TestCases[] = {
- {StaticEnv::Dir, std::errc::is_a_directory},
- {StaticEnv::SymlinkToDir, std::errc::is_a_directory},
- {StaticEnv::BadSymlink, std::errc::no_such_file_or_directory},
- {StaticEnv::DNE, std::errc::no_such_file_or_directory},
- {"", std::errc::no_such_file_or_directory}};
- const uintmax_t expect = static_cast<uintmax_t>(-1);
- for (auto& TC : TestCases) {
- std::error_code ec = GetTestEC();
- TEST_CHECK(file_size(TC.p, ec) == expect);
- TEST_CHECK(ErrorIs(ec, TC.expected_err));
-
- ExceptionChecker Checker(TC.p, TC.expected_err, "file_size");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, file_size(TC.p));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// uintmax_t hard_link_count(const path& p);
-// uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(hard_link_count_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(hard_link_count(p)), uintmax_t);
- ASSERT_SAME_TYPE(decltype(hard_link_count(p, ec)), uintmax_t);
- ASSERT_NOT_NOEXCEPT(hard_link_count(p));
- ASSERT_NOEXCEPT(hard_link_count(p, ec));
-}
-
-TEST_CASE(hard_link_count_for_file)
-{
- TEST_CHECK(hard_link_count(StaticEnv::File) == 1);
- std::error_code ec;
- TEST_CHECK(hard_link_count(StaticEnv::File, ec) == 1);
-}
-
-TEST_CASE(hard_link_count_for_directory)
-{
- uintmax_t DirExpect = 3; // hard link from . .. and Dir2
- uintmax_t Dir3Expect = 2; // hard link from . ..
- uintmax_t DirExpectAlt = DirExpect;
- uintmax_t Dir3ExpectAlt = Dir3Expect;
-#if defined(__APPLE__)
- // Filesystems formatted with case sensitive hfs+ behave unixish as
- // expected. Normal hfs+ filesystems report the number of directory
- // entries instead.
- DirExpectAlt = 5; // . .. Dir2 file1 file2
- Dir3Expect = 3; // . .. file5
-#endif
- TEST_CHECK(hard_link_count(StaticEnv::Dir) == DirExpect ||
- hard_link_count(StaticEnv::Dir) == DirExpectAlt ||
- hard_link_count(StaticEnv::Dir) == 1);
- TEST_CHECK(hard_link_count(StaticEnv::Dir3) == Dir3Expect ||
- hard_link_count(StaticEnv::Dir3) == Dir3ExpectAlt ||
- hard_link_count(StaticEnv::Dir3) == 1);
-
- std::error_code ec;
- TEST_CHECK(hard_link_count(StaticEnv::Dir, ec) == DirExpect ||
- hard_link_count(StaticEnv::Dir, ec) == DirExpectAlt ||
- hard_link_count(StaticEnv::Dir) == 1);
- TEST_CHECK(hard_link_count(StaticEnv::Dir3, ec) == Dir3Expect ||
- hard_link_count(StaticEnv::Dir3, ec) == Dir3ExpectAlt ||
- hard_link_count(StaticEnv::Dir3) == 1);
-}
-TEST_CASE(hard_link_count_increments_test)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- TEST_CHECK(hard_link_count(file) == 1);
-
- env.create_hardlink(file, "file_hl");
- TEST_CHECK(hard_link_count(file) == 2);
-}
-
-
-TEST_CASE(hard_link_count_error_cases)
-{
- const path testCases[] = {
- StaticEnv::BadSymlink,
- StaticEnv::DNE
- };
- const uintmax_t expect = static_cast<uintmax_t>(-1);
- for (auto& TC : testCases) {
- std::error_code ec;
- TEST_CHECK(hard_link_count(TC, ec) == expect);
- TEST_CHECK(ec);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_block_file(file_status s) noexcept
-// bool is_block_file(path const& p);
-// bool is_block_file(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_block_file_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_block_file(s));
- ASSERT_NOEXCEPT(is_block_file(p, ec));
- ASSERT_NOT_NOEXCEPT(is_block_file(p));
-}
-
-TEST_CASE(is_block_file_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, false},
- {file_type::symlink, false},
- {file_type::block, true},
- {file_type::character, false},
- {file_type::fifo, false},
- {file_type::socket, false},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_block_file(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_block_file(p) == false);
-}
-
-TEST_CASE(test_is_block_file_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_block_file(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_block_file(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_character_file(file_status s) noexcept
-// bool is_character_file(path const& p);
-// bool is_character_file(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_character_file_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_character_file(s));
- ASSERT_NOEXCEPT(is_character_file(p, ec));
- ASSERT_NOT_NOEXCEPT(is_character_file(p));
-}
-
-TEST_CASE(is_character_file_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, false},
- {file_type::symlink, false},
- {file_type::block, false},
- {file_type::character, true},
- {file_type::fifo, false},
- {file_type::socket, false},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_character_file(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_character_file(p) == false);
-}
-
-TEST_CASE(test_is_character_file_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_character_file(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_character_file(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_directory(file_status s) noexcept
-// bool is_directory(path const& p);
-// bool is_directory(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_directory_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_directory(s));
- ASSERT_NOEXCEPT(is_directory(p, ec));
- ASSERT_NOT_NOEXCEPT(is_directory(p));
-}
-
-TEST_CASE(is_directory_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, true},
- {file_type::symlink, false},
- {file_type::block, false},
- {file_type::character, false},
- {file_type::fifo, false},
- {file_type::socket, false},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_directory(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_directory(p) == false);
-}
-
-TEST_CASE(static_env_test)
-{
- TEST_CHECK(is_directory(StaticEnv::Dir));
- TEST_CHECK(is_directory(StaticEnv::SymlinkToDir));
- TEST_CHECK(!is_directory(StaticEnv::File));
-}
-
-TEST_CASE(test_is_directory_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dir2 = env.create_dir("dir/dir2");
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_directory(dir2, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_directory(dir2));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_empty(path const& p);
-// bool is_empty(path const& p, std::error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_empty_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(is_empty(p, ec));
- ASSERT_NOT_NOEXCEPT(is_empty(p));
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- std::error_code ec;
- TEST_CHECK(is_empty(p, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK_THROW(filesystem_error, is_empty(p));
-}
-
-TEST_CASE(test_is_empty_directory)
-{
- TEST_CHECK(!is_empty(StaticEnv::Dir));
- TEST_CHECK(!is_empty(StaticEnv::SymlinkToDir));
-}
-
-TEST_CASE(test_is_empty_directory_dynamic)
-{
- scoped_test_env env;
- TEST_CHECK(is_empty(env.test_root));
- env.create_file("foo", 42);
- TEST_CHECK(!is_empty(env.test_root));
-}
-
-TEST_CASE(test_is_empty_file)
-{
- TEST_CHECK(is_empty(StaticEnv::EmptyFile));
- TEST_CHECK(!is_empty(StaticEnv::NonEmptyFile));
-}
-
-TEST_CASE(test_is_empty_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dir2 = env.create_dir("dir/dir2");
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_empty(dir2, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_empty(dir2));
-}
-
-TEST_CASE(test_directory_access_denied)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file1 = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(is_empty(dir, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
-
- TEST_CHECK_THROW(filesystem_error, is_empty(dir));
-}
-
-
-TEST_CASE(test_fifo_fails)
-{
- scoped_test_env env;
- const path fifo = env.create_fifo("fifo");
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(is_empty(fifo, ec) == false);
- TEST_CHECK(ec);
- TEST_CHECK(ec != GetTestEC());
-
- TEST_CHECK_THROW(filesystem_error, is_empty(fifo));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_fifo(file_status s) noexcept
-// bool is_fifo(path const& p);
-// bool is_fifo(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_fifo_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_fifo(s));
- ASSERT_NOEXCEPT(is_fifo(p, ec));
- ASSERT_NOT_NOEXCEPT(is_fifo(p));
-}
-
-TEST_CASE(is_fifo_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, false},
- {file_type::symlink, false},
- {file_type::block, false},
- {file_type::character, false},
- {file_type::fifo, true},
- {file_type::socket, false},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_fifo(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_fifo(p) == false);
-}
-
-TEST_CASE(test_is_fifo_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_fifo(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_fifo(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_other(file_status s) noexcept
-// bool is_other(path const& p);
-// bool is_other(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_other_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_other(s));
- ASSERT_NOEXCEPT(is_other(p, ec));
- ASSERT_NOT_NOEXCEPT(is_other(p));
-}
-
-TEST_CASE(is_other_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, false},
- {file_type::symlink, false},
- {file_type::block, true},
- {file_type::character, true},
- {file_type::fifo, true},
- {file_type::socket, true},
- {file_type::unknown, true}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_other(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_other(p) == false);
-}
-
-TEST_CASE(test_is_other_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_other(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_other(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_regular_file(file_status s) noexcept
-// bool is_regular_file(path const& p);
-// bool is_regular_file(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_regular_file_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_regular_file(s));
- ASSERT_NOEXCEPT(is_regular_file(p, ec));
- ASSERT_NOT_NOEXCEPT(is_regular_file(p));
-}
-
-TEST_CASE(is_regular_file_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, true},
- {file_type::directory, false},
- {file_type::symlink, false},
- {file_type::block, false},
- {file_type::character, false},
- {file_type::fifo, false},
- {file_type::socket, false},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_regular_file(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_regular_file(p) == false);
- std::error_code ec;
- TEST_CHECK(is_regular_file(p, ec) == false);
- TEST_CHECK(ec);
-}
-
-TEST_CASE(test_is_regular_file_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_regular_file(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_regular_file(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_socket(file_status s) noexcept
-// bool is_socket(path const& p);
-// bool is_socket(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_socket_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_socket(s));
- ASSERT_NOEXCEPT(is_socket(p, ec));
- ASSERT_NOT_NOEXCEPT(is_socket(p));
-}
-
-TEST_CASE(is_socket_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, false},
- {file_type::symlink, false},
- {file_type::block, false},
- {file_type::character, false},
- {file_type::fifo, false},
- {file_type::socket, true},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_socket(s) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_socket(p) == false);
-}
-
-TEST_CASE(test_is_socket_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_socket(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_socket(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool is_symlink(file_status s) noexcept
-// bool is_symlink(path const& p);
-// bool is_symlink(path const& p, std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(is_symlink_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOEXCEPT(is_symlink(s));
- ASSERT_NOEXCEPT(is_symlink(p, ec));
- ASSERT_NOT_NOEXCEPT(is_symlink(p));
-}
-
-TEST_CASE(is_symlink_status_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, false},
- {file_type::regular, false},
- {file_type::directory, false},
- {file_type::symlink, true},
- {file_type::block, false},
- {file_type::character, false},
- {file_type::fifo, false},
- {file_type::socket, false},
- {file_type::unknown, false}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(is_symlink(s) == TC.expect);
- }
-}
-
-TEST_CASE(static_env_test)
-{
- struct TestCase {
- path p;
- bool expect;
- };
- const TestCase testCases[] = {
- {StaticEnv::File, false},
- {StaticEnv::Dir, false},
- {StaticEnv::SymlinkToFile, true},
- {StaticEnv::SymlinkToDir, true},
- {StaticEnv::BadSymlink, true}
- };
- for (auto& TC : testCases) {
- TEST_CHECK(is_symlink(TC.p) == TC.expect);
- }
-}
-
-TEST_CASE(test_exist_not_found)
-{
- const path p = StaticEnv::DNE;
- TEST_CHECK(is_symlink(p) == false);
- std::error_code ec;
- TEST_CHECK(is_symlink(p, ec) == false);
- TEST_CHECK(ec);
-}
-
-TEST_CASE(test_is_symlink_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec;
- TEST_CHECK(is_symlink(file, ec) == false);
- TEST_CHECK(ec);
-
- TEST_CHECK_THROW(filesystem_error, is_symlink(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// file_time_type last_write_time(const path& p);
-// file_time_type last_write_time(const path& p, std::error_code& ec) noexcept;
-// void last_write_time(const path& p, file_time_type new_time);
-// void last_write_time(const path& p, file_time_type new_type,
-// std::error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <chrono>
-#include <fstream>
-#include <cstdlib>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-#include <sys/stat.h>
-#include <iostream>
-
-#include <fcntl.h>
-#include <sys/time.h>
-
-using namespace fs;
-
-using TimeSpec = struct ::timespec;
-using StatT = struct ::stat;
-
-using Sec = std::chrono::duration<file_time_type::rep>;
-using Hours = std::chrono::hours;
-using Minutes = std::chrono::minutes;
-using MicroSec = std::chrono::duration<file_time_type::rep, std::micro>;
-using NanoSec = std::chrono::duration<file_time_type::rep, std::nano>;
-using std::chrono::duration_cast;
-
-#if defined(__APPLE__)
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
-#else
-TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
-TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
-#endif
-
-bool ConvertToTimeSpec(TimeSpec& ts, file_time_type ft) {
- using SecFieldT = decltype(TimeSpec::tv_sec);
- using NSecFieldT = decltype(TimeSpec::tv_nsec);
- using SecLim = std::numeric_limits<SecFieldT>;
- using NSecLim = std::numeric_limits<NSecFieldT>;
-
- auto secs = duration_cast<Sec>(ft.time_since_epoch());
- auto nsecs = duration_cast<NanoSec>(ft.time_since_epoch() - secs);
- if (nsecs.count() < 0) {
- if (Sec::min().count() > SecLim::min()) {
- secs += Sec(1);
- nsecs -= Sec(1);
- } else {
- nsecs = NanoSec(0);
- }
- }
- if (SecLim::max() < secs.count() || SecLim::min() > secs.count())
- return false;
- if (NSecLim::max() < nsecs.count() || NSecLim::min() > nsecs.count())
- return false;
- ts.tv_sec = secs.count();
- ts.tv_nsec = nsecs.count();
- return true;
-}
-
-bool ConvertFromTimeSpec(file_time_type& ft, TimeSpec ts) {
- auto secs_part = duration_cast<file_time_type::duration>(Sec(ts.tv_sec));
- if (duration_cast<Sec>(secs_part).count() != ts.tv_sec)
- return false;
- auto subsecs = duration_cast<file_time_type::duration>(NanoSec(ts.tv_nsec));
- auto dur = secs_part + subsecs;
- if (dur < secs_part && subsecs.count() >= 0)
- return false;
- ft = file_time_type(dur);
- return true;
-}
-
-bool CompareTimeExact(TimeSpec ts, TimeSpec ts2) {
- return ts2.tv_sec == ts.tv_sec && ts2.tv_nsec == ts.tv_nsec;
-}
-bool CompareTimeExact(file_time_type ft, TimeSpec ts) {
- TimeSpec ts2 = {};
- if (!ConvertToTimeSpec(ts2, ft))
- return false;
- return CompareTimeExact(ts, ts2);
-}
-bool CompareTimeExact(TimeSpec ts, file_time_type ft) {
- return CompareTimeExact(ft, ts);
-}
-
-struct Times {
- TimeSpec access, write;
-};
-
-Times GetTimes(path const& p) {
- using Clock = file_time_type::clock;
- StatT st;
- if (::stat(p.c_str(), &st) == -1) {
- std::error_code ec(errno, std::generic_category());
-#ifndef TEST_HAS_NO_EXCEPTIONS
- throw ec;
-#else
- std::cerr << ec.message() << std::endl;
- std::exit(EXIT_FAILURE);
-#endif
- }
- return {extract_atime(st), extract_mtime(st)};
-}
-
-TimeSpec LastAccessTime(path const& p) { return GetTimes(p).access; }
-
-TimeSpec LastWriteTime(path const& p) { return GetTimes(p).write; }
-
-std::pair<TimeSpec, TimeSpec> GetSymlinkTimes(path const& p) {
- using Clock = file_time_type::clock;
- StatT st;
- if (::lstat(p.c_str(), &st) == -1) {
- std::error_code ec(errno, std::generic_category());
-#ifndef TEST_HAS_NO_EXCEPTIONS
- throw ec;
-#else
- std::cerr << ec.message() << std::endl;
- std::exit(EXIT_FAILURE);
-#endif
- }
- return {extract_atime(st), extract_mtime(st)};
-}
-
-namespace {
-
-// In some configurations, the comparison is tautological and the test is valid.
-// We disable the warning so that we can actually test it regardless. Also, that
-// diagnostic is pretty new, so also don't fail if old clang does not support it
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunknown-warning-option"
-#pragma clang diagnostic ignored "-Wunknown-pragmas"
-#pragma clang diagnostic ignored "-Wtautological-constant-compare"
-#endif
-
-static const bool SupportsNegativeTimes = [] {
- using namespace std::chrono;
- std::error_code ec;
- TimeSpec old_write_time, new_write_time;
- { // WARNING: Do not assert in this scope.
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- old_write_time = LastWriteTime(file);
- file_time_type tp(seconds(-5));
- fs::last_write_time(file, tp, ec);
- new_write_time = LastWriteTime(file);
- }
-
- return !ec && new_write_time.tv_sec < 0;
-}();
-
-static const bool SupportsMaxTime = [] {
- using namespace std::chrono;
- TimeSpec max_ts = {};
- if (!ConvertToTimeSpec(max_ts, file_time_type::max()))
- return false;
-
- std::error_code ec;
- TimeSpec old_write_time, new_write_time;
- { // WARNING: Do not assert in this scope.
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- old_write_time = LastWriteTime(file);
- file_time_type tp = file_time_type::max();
- fs::last_write_time(file, tp, ec);
- new_write_time = LastWriteTime(file);
- }
- return !ec && new_write_time.tv_sec > max_ts.tv_sec - 1;
-}();
-
-static const bool SupportsMinTime = [] {
- using namespace std::chrono;
- TimeSpec min_ts = {};
- if (!ConvertToTimeSpec(min_ts, file_time_type::min()))
- return false;
- std::error_code ec;
- TimeSpec old_write_time, new_write_time;
- { // WARNING: Do not assert in this scope.
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- old_write_time = LastWriteTime(file);
- file_time_type tp = file_time_type::min();
- fs::last_write_time(file, tp, ec);
- new_write_time = LastWriteTime(file);
- }
- return !ec && new_write_time.tv_sec < min_ts.tv_sec + 1;
-}();
-
-static const bool SupportsNanosecondRoundTrip = [] {
- NanoSec ns(3);
- static_assert(std::is_same<file_time_type::period, std::nano>::value, "");
-
- // Test that the system call we use to set the times also supports nanosecond
- // resolution. (utimes does not)
- file_time_type ft(ns);
- {
- scoped_test_env env;
- const path p = env.create_file("file", 42);
- last_write_time(p, ft);
- return last_write_time(p) == ft;
- }
-}();
-
-// The HFS+ filesystem (used by default before macOS 10.13) stores timestamps at
-// a 1-second granularity, and APFS (now the default) at a 1 nanosecond granularity.
-// 1-second granularity is also the norm on many of the supported filesystems
-// on Linux as well.
-static const bool WorkaroundStatTruncatesToSeconds = [] {
- MicroSec micros(3);
- static_assert(std::is_same<file_time_type::period, std::nano>::value, "");
-
- file_time_type ft(micros);
- {
- scoped_test_env env;
- const path p = env.create_file("file", 42);
- if (LastWriteTime(p).tv_nsec != 0)
- return false;
- last_write_time(p, ft);
- return last_write_time(p) != ft && LastWriteTime(p).tv_nsec == 0;
- }
-}();
-
-static const bool SupportsMinRoundTrip = [] {
- TimeSpec ts = {};
- if (!ConvertToTimeSpec(ts, file_time_type::min()))
- return false;
- file_time_type min_val = {};
- if (!ConvertFromTimeSpec(min_val, ts))
- return false;
- return min_val == file_time_type::min();
-}();
-
-} // end namespace
-
-static bool CompareTime(TimeSpec t1, TimeSpec t2) {
- if (SupportsNanosecondRoundTrip)
- return CompareTimeExact(t1, t2);
- if (t1.tv_sec != t2.tv_sec)
- return false;
-
- auto diff = std::abs(t1.tv_nsec - t2.tv_nsec);
- if (WorkaroundStatTruncatesToSeconds)
- return diff < duration_cast<NanoSec>(Sec(1)).count();
- return diff < duration_cast<NanoSec>(MicroSec(1)).count();
-}
-
-static bool CompareTime(file_time_type t1, TimeSpec t2) {
- TimeSpec ts1 = {};
- if (!ConvertToTimeSpec(ts1, t1))
- return false;
- return CompareTime(ts1, t2);
-}
-
-static bool CompareTime(TimeSpec t1, file_time_type t2) {
- return CompareTime(t2, t1);
-}
-
-static bool CompareTime(file_time_type t1, file_time_type t2) {
- auto min_secs = duration_cast<Sec>(file_time_type::min().time_since_epoch());
- bool IsMin =
- t1.time_since_epoch() < min_secs || t2.time_since_epoch() < min_secs;
-
- if (SupportsNanosecondRoundTrip && (!IsMin || SupportsMinRoundTrip))
- return t1 == t2;
- if (IsMin) {
- return duration_cast<Sec>(t1.time_since_epoch()) ==
- duration_cast<Sec>(t2.time_since_epoch());
- }
- file_time_type::duration dur;
- if (t1 > t2)
- dur = t1 - t2;
- else
- dur = t2 - t1;
- if (WorkaroundStatTruncatesToSeconds)
- return duration_cast<Sec>(dur).count() == 0;
- return duration_cast<MicroSec>(dur).count() == 0;
-}
-
-// Check if a time point is representable on a given filesystem. Check that:
-// (A) 'tp' is representable as a time_t
-// (B) 'tp' is non-negative or the filesystem supports negative times.
-// (C) 'tp' is not 'file_time_type::max()' or the filesystem supports the max
-// value.
-// (D) 'tp' is not 'file_time_type::min()' or the filesystem supports the min
-// value.
-inline bool TimeIsRepresentableByFilesystem(file_time_type tp) {
- TimeSpec ts = {};
- if (!ConvertToTimeSpec(ts, tp))
- return false;
- else if (tp.time_since_epoch().count() < 0 && !SupportsNegativeTimes)
- return false;
- else if (tp == file_time_type::max() && !SupportsMaxTime)
- return false;
- else if (tp == file_time_type::min() && !SupportsMinTime)
- return false;
- return true;
-}
-
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-// Create a sub-second duration using the smallest period the filesystem supports.
-file_time_type::duration SubSec(long long val) {
- using SubSecT = file_time_type::duration;
- if (SupportsNanosecondRoundTrip) {
- return duration_cast<SubSecT>(NanoSec(val));
- } else {
- return duration_cast<SubSecT>(MicroSec(val));
- }
-}
-
-TEST_SUITE(last_write_time_test_suite)
-
-TEST_CASE(signature_test)
-{
- const file_time_type t;
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(last_write_time(p)), file_time_type);
- ASSERT_SAME_TYPE(decltype(last_write_time(p, ec)), file_time_type);
- ASSERT_SAME_TYPE(decltype(last_write_time(p, t)), void);
- ASSERT_SAME_TYPE(decltype(last_write_time(p, t, ec)), void);
- ASSERT_NOT_NOEXCEPT(last_write_time(p));
- ASSERT_NOT_NOEXCEPT(last_write_time(p, t));
- ASSERT_NOEXCEPT(last_write_time(p, ec));
- ASSERT_NOEXCEPT(last_write_time(p, t, ec));
-}
-
-TEST_CASE(read_last_write_time_static_env_test)
-{
- using C = file_time_type::clock;
- file_time_type min = file_time_type::min();
- {
- file_time_type ret = last_write_time(StaticEnv::File);
- TEST_CHECK(ret != min);
- TEST_CHECK(ret < C::now());
- TEST_CHECK(CompareTime(ret, LastWriteTime(StaticEnv::File)));
-
- file_time_type ret2 = last_write_time(StaticEnv::SymlinkToFile);
- TEST_CHECK(CompareTime(ret, ret2));
- TEST_CHECK(CompareTime(ret2, LastWriteTime(StaticEnv::SymlinkToFile)));
- }
- {
- file_time_type ret = last_write_time(StaticEnv::Dir);
- TEST_CHECK(ret != min);
- TEST_CHECK(ret < C::now());
- TEST_CHECK(CompareTime(ret, LastWriteTime(StaticEnv::Dir)));
-
- file_time_type ret2 = last_write_time(StaticEnv::SymlinkToDir);
- TEST_CHECK(CompareTime(ret, ret2));
- TEST_CHECK(CompareTime(ret2, LastWriteTime(StaticEnv::SymlinkToDir)));
- }
-}
-
-TEST_CASE(get_last_write_time_dynamic_env_test)
-{
- using Clock = file_time_type::clock;
- using Sec = std::chrono::seconds;
- scoped_test_env env;
-
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
-
- const auto file_times = GetTimes(file);
- const TimeSpec file_write_time = file_times.write;
- const auto dir_times = GetTimes(dir);
- const TimeSpec dir_write_time = dir_times.write;
-
- file_time_type ftime = last_write_time(file);
- TEST_CHECK(Clock::to_time_t(ftime) == file_write_time.tv_sec);
- TEST_CHECK(CompareTime(ftime, file_write_time));
-
- file_time_type dtime = last_write_time(dir);
- TEST_CHECK(Clock::to_time_t(dtime) == dir_write_time.tv_sec);
- TEST_CHECK(CompareTime(dtime, dir_write_time));
-
- SleepFor(Sec(2));
-
- // update file and add a file to the directory. Make sure the times increase.
- std::ofstream of(file, std::ofstream::app);
- of << "hello";
- of.close();
- env.create_file("dir/file1", 1);
-
- file_time_type ftime2 = last_write_time(file);
- file_time_type dtime2 = last_write_time(dir);
-
- TEST_CHECK(ftime2 > ftime);
- TEST_CHECK(dtime2 > dtime);
- TEST_CHECK(CompareTime(LastWriteTime(file), ftime2));
- TEST_CHECK(CompareTime(LastWriteTime(dir), dtime2));
-}
-
-
-TEST_CASE(set_last_write_time_dynamic_env_test)
-{
- using Clock = file_time_type::clock;
- scoped_test_env env;
-
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
- const auto now = Clock::now();
- const file_time_type epoch_time = now - now.time_since_epoch();
-
- const file_time_type future_time = now + Hours(3) + Sec(42) + SubSec(17);
- const file_time_type past_time = now - Minutes(3) - Sec(42) - SubSec(17);
- const file_time_type before_epoch_time =
- epoch_time - Minutes(3) - Sec(42) - SubSec(17);
- // FreeBSD has a bug in their utimes implementation where the time is not update
- // when the number of seconds is '-1'.
-#if defined(__FreeBSD__)
- const file_time_type just_before_epoch_time =
- epoch_time - Sec(2) - SubSec(17);
-#else
- const file_time_type just_before_epoch_time = epoch_time - SubSec(17);
-#endif
-
- struct TestCase {
- const char * case_name;
- path p;
- file_time_type new_time;
- } cases[] = {
- {"file, epoch_time", file, epoch_time},
- {"dir, epoch_time", dir, epoch_time},
- {"file, future_time", file, future_time},
- {"dir, future_time", dir, future_time},
- {"file, past_time", file, past_time},
- {"dir, past_time", dir, past_time},
- {"file, before_epoch_time", file, before_epoch_time},
- {"dir, before_epoch_time", dir, before_epoch_time},
- {"file, just_before_epoch_time", file, just_before_epoch_time},
- {"dir, just_before_epoch_time", dir, just_before_epoch_time}
- };
- for (const auto& TC : cases) {
- std::cerr << "Test Case = " << TC.case_name << "\n";
- const auto old_times = GetTimes(TC.p);
- file_time_type old_time;
- TEST_REQUIRE(ConvertFromTimeSpec(old_time, old_times.write));
-
- std::error_code ec = GetTestEC();
- last_write_time(TC.p, TC.new_time, ec);
- TEST_CHECK(!ec);
-
- ec = GetTestEC();
- file_time_type got_time = last_write_time(TC.p, ec);
- TEST_REQUIRE(!ec);
-
- if (TimeIsRepresentableByFilesystem(TC.new_time)) {
- TEST_CHECK(got_time != old_time);
- TEST_CHECK(CompareTime(got_time, TC.new_time));
- TEST_CHECK(CompareTime(LastAccessTime(TC.p), old_times.access));
- }
- }
-}
-
-TEST_CASE(last_write_time_symlink_test)
-{
- using Clock = file_time_type::clock;
-
- scoped_test_env env;
-
- const path file = env.create_file("file", 42);
- const path sym = env.create_symlink("file", "sym");
-
- const file_time_type new_time = Clock::now() + Hours(3);
-
- const auto old_times = GetTimes(sym);
- const auto old_sym_times = GetSymlinkTimes(sym);
-
- std::error_code ec = GetTestEC();
- last_write_time(sym, new_time, ec);
- TEST_CHECK(!ec);
-
- file_time_type got_time = last_write_time(sym);
- TEST_CHECK(!CompareTime(got_time, old_times.write));
- if (!WorkaroundStatTruncatesToSeconds) {
- TEST_CHECK(got_time == new_time);
- } else {
- TEST_CHECK(CompareTime(got_time, new_time));
- }
-
- TEST_CHECK(CompareTime(LastWriteTime(file), new_time));
- TEST_CHECK(CompareTime(LastAccessTime(sym), old_times.access));
- std::pair<TimeSpec, TimeSpec> sym_times = GetSymlinkTimes(sym);
- TEST_CHECK(CompareTime(sym_times.first, old_sym_times.first));
- TEST_CHECK(CompareTime(sym_times.second, old_sym_times.second));
-}
-
-
-TEST_CASE(test_write_min_time)
-{
- using Clock = file_time_type::clock;
- scoped_test_env env;
- const path p = env.create_file("file", 42);
- const file_time_type old_time = last_write_time(p);
- file_time_type new_time = file_time_type::min();
-
- std::error_code ec = GetTestEC();
- last_write_time(p, new_time, ec);
- file_time_type tt = last_write_time(p);
-
- if (TimeIsRepresentableByFilesystem(new_time)) {
- TEST_CHECK(!ec);
- TEST_CHECK(CompareTime(tt, new_time));
-
- last_write_time(p, old_time);
- new_time = file_time_type::min() + SubSec(1);
-
- ec = GetTestEC();
- last_write_time(p, new_time, ec);
- tt = last_write_time(p);
-
- if (TimeIsRepresentableByFilesystem(new_time)) {
- TEST_CHECK(!ec);
- TEST_CHECK(CompareTime(tt, new_time));
- } else {
- TEST_CHECK(ErrorIs(ec, std::errc::value_too_large));
- TEST_CHECK(tt == old_time);
- }
- } else {
- TEST_CHECK(ErrorIs(ec, std::errc::value_too_large));
- TEST_CHECK(tt == old_time);
- }
-}
-
-TEST_CASE(test_write_max_time) {
- using Clock = file_time_type::clock;
- using Sec = std::chrono::seconds;
- using Hours = std::chrono::hours;
-
- scoped_test_env env;
- const path p = env.create_file("file", 42);
- const file_time_type old_time = last_write_time(p);
- file_time_type new_time = file_time_type::max();
-
- std::error_code ec = GetTestEC();
- last_write_time(p, new_time, ec);
- file_time_type tt = last_write_time(p);
-
- if (TimeIsRepresentableByFilesystem(new_time)) {
- TEST_CHECK(!ec);
- TEST_CHECK(CompareTime(tt, new_time));
- } else {
- TEST_CHECK(ErrorIs(ec, std::errc::value_too_large));
- TEST_CHECK(tt == old_time);
- }
-}
-
-TEST_CASE(test_value_on_failure)
-{
- const path p = StaticEnv::DNE;
- std::error_code ec = GetTestEC();
- TEST_CHECK(last_write_time(p, ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
-}
-
-TEST_CASE(test_exists_fails)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- permissions(dir, perms::none);
-
- std::error_code ec = GetTestEC();
- TEST_CHECK(last_write_time(file, ec) == file_time_type::min());
- TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
-
- ExceptionChecker Checker(file, std::errc::permission_denied,
- "last_write_time");
- TEST_CHECK_THROW_RESULT(filesystem_error, Checker, last_write_time(file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void permissions(const path& p, perms prms,
-// perm_options opts = perm_options::replace);
-// void permissions(const path& p, perms prms, std::error_code& ec) noexcept;
-// void permissions(const path& p, perms prms, perm_options opts, std::error_code);
-
-
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-using PR = fs::perms;
-
-TEST_SUITE(filesystem_permissions_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- const perms pr{}; ((void)pr);
- const perm_options opts{}; ((void)opts);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr));
- ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr, opts));
- ASSERT_NOEXCEPT(fs::permissions(p, pr, ec));
- ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr, opts, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, fs::perms opts,
- const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::permissions(f, opts);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == ""
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)opts); ((void)ec);
- return true;
-#endif
- };
-
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path dne_sym = env.create_symlink(dne, "dne_sym");
- { // !exists
- std::error_code ec = GetTestEC();
- fs::permissions(dne, fs::perms{}, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(ec != GetTestEC());
- TEST_CHECK(checkThrow(dne, fs::perms{}, ec));
- }
- {
- std::error_code ec = GetTestEC();
- fs::permissions(dne_sym, fs::perms{}, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(ec != GetTestEC());
- TEST_CHECK(checkThrow(dne_sym, fs::perms{}, ec));
- }
-}
-
-TEST_CASE(basic_permissions_test)
-{
- scoped_test_env env;
- const path file = env.create_file("file1", 42);
- const path dir = env.create_dir("dir1");
- const path file_for_sym = env.create_file("file2", 42);
- const path sym = env.create_symlink(file_for_sym, "sym");
- const perm_options AP = perm_options::add;
- const perm_options RP = perm_options::remove;
- const perm_options NF = perm_options::nofollow;
- struct TestCase {
- path p;
- perms set_perms;
- perms expected;
- perm_options opts;
- TestCase(path xp, perms xperms, perms xexpect,
- perm_options xopts = perm_options::replace)
- : p(xp), set_perms(xperms), expected(xexpect), opts(xopts) {}
- } cases[] = {
- // test file
- {file, perms::none, perms::none},
- {file, perms::owner_all, perms::owner_all},
- {file, perms::group_all, perms::owner_all | perms::group_all, AP},
- {file, perms::group_all, perms::owner_all, RP},
- // test directory
- {dir, perms::none, perms::none},
- {dir, perms::owner_all, perms::owner_all},
- {dir, perms::group_all, perms::owner_all | perms::group_all, AP},
- {dir, perms::group_all, perms::owner_all, RP},
- // test symlink without symlink_nofollow
- {sym, perms::none, perms::none},
- {sym, perms::owner_all, perms::owner_all},
- {sym, perms::group_all, perms::owner_all | perms::group_all, AP},
- {sym, perms::group_all, perms::owner_all, RP},
- // test non-symlink with symlink_nofollow. The last test on file/dir
- // will have set their permissions to perms::owner_all
- {file, perms::group_all, perms::owner_all | perms::group_all, AP | NF},
- {dir, perms::group_all, perms::owner_all | perms::group_all, AP | NF}
- };
- for (auto const& TC : cases) {
- TEST_CHECK(status(TC.p).permissions() != TC.expected);
- {
- std::error_code ec = GetTestEC();
- permissions(TC.p, TC.set_perms, TC.opts, ec);
- TEST_CHECK(!ec);
- auto pp = status(TC.p).permissions();
- TEST_CHECK(pp == TC.expected);
- }
- if (TC.opts == perm_options::replace) {
- std::error_code ec = GetTestEC();
- permissions(TC.p, TC.set_perms, ec);
- TEST_CHECK(!ec);
- auto pp = status(TC.p).permissions();
- TEST_CHECK(pp == TC.expected);
- }
- }
-}
-
-TEST_CASE(test_no_resolve_symlink_on_symlink)
-{
- scoped_test_env env;
- const path file = env.create_file("file", 42);
- const path sym = env.create_symlink(file, "sym");
- const auto file_perms = status(file).permissions();
-
- struct TestCase {
- perms set_perms;
- perms expected; // only expected on platform that support symlink perms.
- perm_options opts = perm_options::replace;
- TestCase(perms xperms, perms xexpect,
- perm_options xopts = perm_options::replace)
- : set_perms(xperms), expected(xexpect), opts(xopts) {}
- } cases[] = {
- {perms::owner_all, perms::owner_all},
- {perms::group_all, perms::owner_all | perms::group_all, perm_options::add},
- {perms::owner_all, perms::group_all, perm_options::remove},
- };
- for (auto const& TC : cases) {
-#if defined(__APPLE__) || defined(__FreeBSD__)
- // On OS X symlink permissions are supported. We should get an empty
- // error code and the expected permissions.
- const auto expected_link_perms = TC.expected;
- std::error_code expected_ec;
-#else
- // On linux symlink permissions are not supported. The error code should
- // be 'operation_not_supported' and the symlink permissions should be
- // unchanged.
- const auto expected_link_perms = symlink_status(sym).permissions();
- std::error_code expected_ec = std::make_error_code(std::errc::operation_not_supported);
-#endif
- std::error_code ec = GetTestEC();
- permissions(sym, TC.set_perms, TC.opts | perm_options::nofollow, ec);
- TEST_CHECK(ec == expected_ec);
- TEST_CHECK(status(file).permissions() == file_perms);
- TEST_CHECK(symlink_status(sym).permissions() == expected_link_perms);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// 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);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <iostream>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-static int count_path_elems(const fs::path& p) {
- int count = 0;
- for (auto& elem : p) {
- if (elem != "/" && elem != "")
- ++count;
- }
- return count;
-}
-
-TEST_SUITE(filesystem_proximate_path_test_suite)
-
-
-TEST_CASE(signature_test)
-{
- using fs::path;
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(proximate(p));
- ASSERT_NOT_NOEXCEPT(proximate(p, p));
- ASSERT_NOT_NOEXCEPT(proximate(p, ec));
- ASSERT_NOT_NOEXCEPT(proximate(p, p, ec));
-}
-
-TEST_CASE(basic_test) {
- using fs::path;
- const path cwd = fs::current_path();
- const path parent_cwd = cwd.parent_path();
- const path curdir = cwd.filename();
- TEST_REQUIRE(!cwd.native().empty());
- int cwd_depth = count_path_elems(cwd);
- path dot_dot_to_root;
- for (int i=0; i < cwd_depth; ++i)
- dot_dot_to_root /= "..";
- path relative_cwd = cwd.native().substr(1);
- // clang-format off
- struct {
- std::string input;
- std::string base;
- std::string expect;
- } TestCases[] = {
- {"", "", "."},
- {cwd, "a", ".."},
- {parent_cwd, "a", "../.."},
- {"a", cwd, "a"},
- {"a", parent_cwd, "fs.op.proximate/a"},
- {"/", "a", dot_dot_to_root / ".."},
- {"/", "a/b", dot_dot_to_root / "../.."},
- {"/", "a/b/", dot_dot_to_root / "../../.."},
- {"a", "/", relative_cwd / "a"},
- {"a/b", "/", relative_cwd / "a/b"},
- {"a", "/net", ".." / relative_cwd / "a"},
- {"//foo/", "//foo", "/foo/"},
- {"//foo", "//foo/", ".."},
- {"//foo", "//foo", "."},
- {"//foo/", "//foo/", "."},
- {"//base", "a", dot_dot_to_root / "../base"},
- {"a", "a", "."},
- {"a/b", "a/b", "."},
- {"a/b/c/", "a/b/c/", "."},
- {"//foo/a/b", "//foo/a/b", "."},
- {"/a/d", "/a/b/c", "../../d"},
- {"/a/b/c", "/a/d", "../b/c"},
- {"a/b/c", "a", "b/c"},
- {"a/b/c", "a/b/c/x/y", "../.."},
- {"a/b/c", "a/b/c", "."},
- {"a/b", "c/d", "../../a/b"}
- };
- // clang-format on
- int ID = 0;
- for (auto& TC : TestCases) {
- ++ID;
- std::error_code ec = GetTestEC();
- fs::path p(TC.input);
- const fs::path output = fs::proximate(p, TC.base, ec);
- if (ec) {
- TEST_CHECK(!ec);
- std::cerr << "TEST CASE #" << ID << " FAILED: \n";
- std::cerr << " Input: '" << TC.input << "'\n";
- std::cerr << " Base: '" << TC.base << "'\n";
- std::cerr << " Expected: '" << TC.expect << "'\n";
-
- std::cerr << std::endl;
- } else if (!PathEq(output, TC.expect)) {
- TEST_CHECK(PathEq(output, TC.expect));
-
- const path canon_input = fs::weakly_canonical(TC.input);
- const path canon_base = fs::weakly_canonical(TC.base);
- const path lexically_p = canon_input.lexically_proximate(canon_base);
- std::cerr << "TEST CASE #" << ID << " FAILED: \n";
- std::cerr << " Input: '" << TC.input << "'\n";
- std::cerr << " Base: '" << TC.base << "'\n";
- std::cerr << " Expected: '" << TC.expect << "'\n";
- std::cerr << " Output: '" << output.native() << "'\n";
- std::cerr << " Lex Prox: '" << lexically_p.native() << "'\n";
- std::cerr << " Canon Input: " << canon_input << "\n";
- std::cerr << " Canon Base: " << canon_base << "\n";
-
- std::cerr << std::endl;
- }
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path read_symlink(const path& p);
-// path read_symlink(const path& p, error_code& ec);
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_read_symlink_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::read_symlink(p)), fs::path);
- ASSERT_SAME_TYPE(decltype(fs::read_symlink(p, ec)), fs::path);
-
- ASSERT_NOT_NOEXCEPT(fs::read_symlink(p));
- // Not noexcept because of narrow contract
- ASSERT_NOT_NOEXCEPT(fs::read_symlink(p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::read_symlink(f);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == ""
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)ec);
- return true;
-#endif
- };
-
- scoped_test_env env;
- const path cases[] = {
- env.make_env_path("dne"),
- env.create_file("file", 42),
- env.create_dir("dir")
- };
- for (path const& p : cases) {
- std::error_code ec;
- const path ret = fs::read_symlink(p, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(ret == path{});
- TEST_CHECK(checkThrow(p, ec));
- }
-
-}
-
-TEST_CASE(basic_symlink_test)
-{
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path file = env.create_file("file", 42);
- const path dir = env.create_dir("dir");
- const path link = env.create_symlink(dne, "link");
- const path nested_link = env.make_env_path("nested_link");
- create_symlink(link, nested_link);
- struct TestCase {
- path symlink;
- path expected;
- } testCases[] = {
- {env.create_symlink(dne, "dne_link"), dne},
- {env.create_symlink(file, "file_link"), file},
- {env.create_symlink(dir, "dir_link"), dir},
- {nested_link, link}
- };
- for (auto& TC : testCases) {
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- const path ret = read_symlink(TC.symlink, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ret == TC.expected);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// 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);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <iostream>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-TEST_SUITE(filesystem_proximate_path_test_suite)
-
-TEST_CASE(test_signature) {
-
-}
-int main() {
- // clang-format off
- struct {
- std::string input;
- std::string expect;
- } TestCases[] = {
- {"", fs::current_path()},
- {".", fs::current_path()},
- {StaticEnv::File, StaticEnv::File},
- {StaticEnv::Dir, StaticEnv::Dir},
- {StaticEnv::SymlinkToDir, StaticEnv::Dir},
- {StaticEnv::SymlinkToDir / "dir2/.", StaticEnv::Dir / "dir2"},
- // FIXME? If the trailing separator occurs in a part of the path that exists,
- // it is ommitted. Otherwise it is added to the end of the result.
- {StaticEnv::SymlinkToDir / "dir2/./", StaticEnv::Dir / "dir2"},
- {StaticEnv::SymlinkToDir / "dir2/DNE/./", StaticEnv::Dir / "dir2/DNE/"},
- {StaticEnv::SymlinkToDir / "dir2", StaticEnv::Dir2},
- {StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/..", StaticEnv::Dir2 / ""},
- {StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2", StaticEnv::Dir2 / "DNE/DNE2"},
- {StaticEnv::Dir / "../dir1", StaticEnv::Dir},
- {StaticEnv::Dir / "./.", StaticEnv::Dir},
- {StaticEnv::Dir / "DNE/../foo", StaticEnv::Dir / "foo"}
- };
- // clang-format on
- int ID = 0;
- bool Failed = false;
- for (auto& TC : TestCases) {
- ++ID;
- fs::path p(TC.input);
- const fs::path output = fs::weakly_canonical(p);
- if (output != TC.expect) {
- Failed = true;
- std::cerr << "TEST CASE #" << ID << " FAILED: \n";
- std::cerr << " Input: '" << TC.input << "'\n";
- std::cerr << " Expected: '" << TC.expect << "'\n";
- std::cerr << " Output: '" << output.native() << "'";
- std::cerr << std::endl;
- }
- }
- return Failed;
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool remove(const path& p);
-// bool remove(const path& p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_remove_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::remove(p)), bool);
- ASSERT_SAME_TYPE(decltype(fs::remove(p, ec)), bool);
-
- ASSERT_NOT_NOEXCEPT(fs::remove(p));
- ASSERT_NOEXCEPT(fs::remove(p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::remove(f);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == ""
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)ec);
- return true;
-#endif
- };
- scoped_test_env env;
- const path non_empty_dir = env.create_dir("dir");
- env.create_file(non_empty_dir / "file1", 42);
- const path bad_perms_dir = env.create_dir("bad_dir");
- const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42);
- permissions(bad_perms_dir, perms::none);
- const path testCases[] = {
- non_empty_dir,
- file_in_bad_dir,
- };
- for (auto& p : testCases) {
- std::error_code ec;
-
- TEST_CHECK(!fs::remove(p, ec));
- TEST_CHECK(ec);
- TEST_CHECK(checkThrow(p, ec));
- }
-
- // PR#35780
- const path testCasesNonexistant[] = {
- "",
- env.make_env_path("dne")
- };
-
- for (auto& p : testCasesNonexistant) {
- std::error_code ec;
-
- TEST_CHECK(!fs::remove(p, ec));
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(basic_remove_test)
-{
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path link = env.create_symlink(dne, "link");
- const path nested_link = env.make_env_path("nested_link");
- create_symlink(link, nested_link);
- const path testCases[] = {
- env.create_file("file", 42),
- env.create_dir("empty_dir"),
- nested_link,
- link
- };
- for (auto& p : testCases) {
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- TEST_CHECK(remove(p, ec));
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(symlink_status(p)));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// uintmax_t remove_all(const path& p);
-// uintmax_t remove_all(const path& p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_remove_all_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::remove_all(p)), std::uintmax_t);
- ASSERT_SAME_TYPE(decltype(fs::remove_all(p, ec)), std::uintmax_t);
-
- ASSERT_NOT_NOEXCEPT(fs::remove_all(p));
- ASSERT_NOT_NOEXCEPT(fs::remove_all(p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::remove_all(f);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == ""
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)ec);
- return true;
-#endif
- };
- scoped_test_env env;
- const path non_empty_dir = env.create_dir("dir");
- env.create_file(non_empty_dir / "file1", 42);
- const path bad_perms_dir = env.create_dir("bad_dir");
- const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42);
- permissions(bad_perms_dir, perms::none);
- const path bad_perms_file = env.create_file("file2", 42);
- permissions(bad_perms_file, perms::none);
-
- const path testCases[] = {
- file_in_bad_dir
- };
- const auto BadRet = static_cast<std::uintmax_t>(-1);
- for (auto& p : testCases) {
- std::error_code ec;
-
- TEST_CHECK(fs::remove_all(p, ec) == BadRet);
- TEST_CHECK(ec);
- TEST_CHECK(checkThrow(p, ec));
- }
-
- // PR#35780
- const path testCasesNonexistant[] = {
- "",
- env.make_env_path("dne")
- };
- for (auto &p : testCasesNonexistant) {
- std::error_code ec;
-
- TEST_CHECK(fs::remove_all(p, ec) == 0);
- TEST_CHECK(!ec);
- }
-}
-
-TEST_CASE(basic_remove_all_test)
-{
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path link = env.create_symlink(dne, "link");
- const path nested_link = env.make_env_path("nested_link");
- create_symlink(link, nested_link);
- const path testCases[] = {
- env.create_file("file", 42),
- env.create_dir("empty_dir"),
- nested_link,
- link
- };
- for (auto& p : testCases) {
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- TEST_CHECK(remove(p, ec));
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(symlink_status(p)));
- }
-}
-
-TEST_CASE(symlink_to_dir)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file(dir / "file", 42);
- const path link = env.create_symlink(dir, "sym");
-
- {
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- TEST_CHECK(remove_all(link, ec) == 1);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(symlink_status(link)));
- TEST_CHECK(exists(dir));
- TEST_CHECK(exists(file));
- }
-}
-
-
-TEST_CASE(nested_dir)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path dir1 = env.create_dir(dir / "dir1");
- const path out_of_dir_file = env.create_file("file1", 42);
- const path all_files[] = {
- dir, dir1,
- env.create_file(dir / "file1", 42),
- env.create_symlink(out_of_dir_file, dir / "sym1"),
- env.create_file(dir1 / "file2", 42),
- env.create_symlink(dir, dir1 / "sym2")
- };
- const std::size_t expected_count = sizeof(all_files) / sizeof(all_files[0]);
-
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- TEST_CHECK(remove_all(dir, ec) == expected_count);
- TEST_CHECK(!ec);
- for (auto const& p : all_files) {
- TEST_CHECK(!exists(symlink_status(p)));
- }
- TEST_CHECK(exists(out_of_dir_file));
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void rename(const path& old_p, const path& new_p);
-// void rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_rename_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(fs::rename(p, p)), void);
- ASSERT_SAME_TYPE(decltype(fs::rename(p, p, ec)), void);
-
- ASSERT_NOT_NOEXCEPT(fs::rename(p, p));
- ASSERT_NOEXCEPT(fs::rename(p, p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::rename(f, t);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == t
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)t); ((void)ec);
- return true;
-#endif
- };
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path file = env.create_file("file1", 42);
- const path dir = env.create_dir("dir1");
- struct TestCase {
- path from;
- path to;
- } cases[] = {
- {dne, dne},
- {file, dir},
- {dir, file}
- };
- for (auto& TC : cases) {
- auto from_before = status(TC.from);
- auto to_before = status(TC.to);
- std::error_code ec;
- rename(TC.from, TC.to, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(from_before.type() == status(TC.from).type());
- TEST_CHECK(to_before.type() == status(TC.to).type());
- TEST_CHECK(checkThrow(TC.from, TC.to, ec));
- }
-}
-
-TEST_CASE(basic_rename_test)
-{
- scoped_test_env env;
-
- const std::error_code set_ec = std::make_error_code(std::errc::address_in_use);
- const path file = env.create_file("file1", 42);
- { // same file
- std::error_code ec = set_ec;
- rename(file, file, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(is_regular_file(file));
- TEST_CHECK(file_size(file) == 42);
- }
- const path sym = env.create_symlink(file, "sym");
- { // file -> symlink
- std::error_code ec = set_ec;
- rename(file, sym, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(file));
- TEST_CHECK(is_regular_file(symlink_status(sym)));
- TEST_CHECK(file_size(sym) == 42);
- }
- const path file2 = env.create_file("file2", 42);
- const path file3 = env.create_file("file3", 100);
- { // file -> file
- std::error_code ec = set_ec;
- rename(file2, file3, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(file2));
- TEST_CHECK(is_regular_file(file3));
- TEST_CHECK(file_size(file3) == 42);
- }
- const path dne = env.make_env_path("dne");
- const path bad_sym = env.create_symlink(dne, "bad_sym");
- const path bad_sym_dest = env.make_env_path("bad_sym2");
- { // bad-symlink
- std::error_code ec = set_ec;
- rename(bad_sym, bad_sym_dest, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(!exists(symlink_status(bad_sym)));
- TEST_CHECK(is_symlink(bad_sym_dest));
- TEST_CHECK(read_symlink(bad_sym_dest) == dne);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// void resize_file(const path& p, uintmax_t new_size);
-// void resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_resize_file_test_suite)
-
-TEST_CASE(test_signatures)
-{
- const path p; ((void)p);
- std::uintmax_t i; ((void)i);
- std::error_code ec; ((void)ec);
-
- ASSERT_SAME_TYPE(decltype(fs::resize_file(p, i)), void);
- ASSERT_SAME_TYPE(decltype(fs::resize_file(p, i, ec)), void);
-
- ASSERT_NOT_NOEXCEPT(fs::resize_file(p, i));
- ASSERT_NOEXCEPT(fs::resize_file(p, i, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, std::uintmax_t s, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- fs::resize_file(f, s);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == ""
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)s); ((void)ec);
- return true;
-#endif
- };
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path bad_sym = env.create_symlink(dne, "sym");
- const path dir = env.create_dir("dir1");
- const path cases[] = {
- dne, bad_sym, dir
- };
- for (auto& p : cases) {
- std::error_code ec;
- resize_file(p, 42, ec);
- TEST_REQUIRE(ec);
- TEST_CHECK(checkThrow(p, 42, ec));
- }
-}
-
-TEST_CASE(basic_resize_file_test)
-{
- scoped_test_env env;
- const path file1 = env.create_file("file1", 42);
- const auto set_ec = std::make_error_code(std::errc::address_in_use);
- { // grow file
- const std::uintmax_t new_s = 100;
- std::error_code ec = set_ec;
- resize_file(file1, new_s, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(file1) == new_s);
- }
- { // shrink file
- const std::uintmax_t new_s = 1;
- std::error_code ec = set_ec;
- resize_file(file1, new_s, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(file1) == new_s);
- }
- { // shrink file to zero
- const std::uintmax_t new_s = 0;
- std::error_code ec = set_ec;
- resize_file(file1, new_s, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(file1) == new_s);
- }
- const path sym = env.create_symlink(file1, "sym");
- { // grow file via symlink
- const std::uintmax_t new_s = 1024;
- std::error_code ec = set_ec;
- resize_file(sym, new_s, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(file_size(file1) == new_s);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// space_info space(const path& p);
-// space_info space(const path& p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-#include <sys/statvfs.h>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-bool EqualDelta(std::uintmax_t x, std::uintmax_t y, std::uintmax_t delta) {
- if (x >= y) {
- return (x - y) <= delta;
- } else {
- return (y - x) <= delta;
- }
-}
-
-TEST_SUITE(filesystem_space_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_SAME_TYPE(decltype(space(p)), space_info);
- ASSERT_SAME_TYPE(decltype(space(p, ec)), space_info);
- ASSERT_NOT_NOEXCEPT(space(p));
- ASSERT_NOEXCEPT(space(p, ec));
-}
-
-TEST_CASE(test_error_reporting)
-{
- auto checkThrow = [](path const& f, const std::error_code& ec)
- {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- try {
- space(f);
- return false;
- } catch (filesystem_error const& err) {
- return err.path1() == f
- && err.path2() == ""
- && err.code() == ec;
- }
-#else
- ((void)f); ((void)ec);
- return true;
-#endif
- };
- const path cases[] = {
- "",
- StaticEnv::DNE,
- StaticEnv::BadSymlink
- };
- for (auto& p : cases) {
- const auto expect = static_cast<std::uintmax_t>(-1);
- std::error_code ec;
- space_info info = space(p, ec);
- TEST_CHECK(ec);
- TEST_CHECK(info.capacity == expect);
- TEST_CHECK(info.free == expect);
- TEST_CHECK(info.available == expect);
- TEST_CHECK(checkThrow(p, ec));
- }
-}
-
-TEST_CASE(basic_space_test)
-{
- // All the test cases should reside on the same filesystem and therefore
- // should have the same expected result. Compute this expected result
- // one and check that it looks semi-sane.
- struct statvfs expect;
- TEST_REQUIRE(::statvfs(StaticEnv::Dir.c_str(), &expect) != -1);
- TEST_CHECK(expect.f_bavail > 0);
- TEST_CHECK(expect.f_bfree > 0);
- TEST_CHECK(expect.f_bsize > 0);
- TEST_CHECK(expect.f_blocks > 0);
- TEST_REQUIRE(expect.f_frsize > 0);
- auto do_mult = [&](std::uintmax_t val) {
- std::uintmax_t fsize = expect.f_frsize;
- std::uintmax_t new_val = val * fsize;
- TEST_CHECK(new_val / fsize == val); // Test for overflow
- return new_val;
- };
- const std::uintmax_t bad_value = static_cast<std::uintmax_t>(-1);
- const std::uintmax_t expect_capacity = do_mult(expect.f_blocks);
- const std::uintmax_t expect_free = do_mult(expect.f_bfree);
- const std::uintmax_t expect_avail = do_mult(expect.f_bavail);
-
- // Other processes running on the operating system may have changed
- // the amount of space available. Check that these are within tolerances.
- // Currently 5% of capacity
- const std::uintmax_t delta = expect_capacity / 20;
- const path cases[] = {
- StaticEnv::File,
- StaticEnv::Dir,
- StaticEnv::Dir2,
- StaticEnv::SymlinkToFile,
- StaticEnv::SymlinkToDir
- };
- for (auto& p : cases) {
- std::error_code ec = GetTestEC();
- space_info info = space(p, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(info.capacity != bad_value);
- TEST_CHECK(expect_capacity == info.capacity);
- TEST_CHECK(info.free != bad_value);
- TEST_CHECK(EqualDelta(expect_free, info.free, delta));
- TEST_CHECK(info.available != bad_value);
- TEST_CHECK(EqualDelta(expect_avail, info.available, delta));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// file_status status(const path& p);
-// file_status status(const path& p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_status_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(status(p));
- ASSERT_NOEXCEPT(status(p, ec));
-}
-
-TEST_CASE(test_status_not_found)
-{
- const std::error_code expect_ec =
- std::make_error_code(std::errc::no_such_file_or_directory);
- const path cases[] {
- StaticEnv::DNE,
- StaticEnv::BadSymlink
- };
- for (auto& p : cases) {
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- // test non-throwing overload.
- file_status st = status(p, ec);
- TEST_CHECK(ec == expect_ec);
- TEST_CHECK(st.type() == file_type::not_found);
- TEST_CHECK(st.permissions() == perms::unknown);
- // test throwing overload. It should not throw even though it reports
- // that the file was not found.
- TEST_CHECK_NO_THROW(st = status(p));
- TEST_CHECK(st.type() == file_type::not_found);
- TEST_CHECK(st.permissions() == perms::unknown);
- }
-}
-
-TEST_CASE(test_status_cannot_resolve)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file = env.create_file("dir/file", 42);
- const path sym = env.create_symlink("dir/file", "sym");
- permissions(dir, perms::none);
-
- const std::error_code set_ec =
- std::make_error_code(std::errc::address_in_use);
- const std::error_code perm_ec =
- std::make_error_code(std::errc::permission_denied);
- const std::error_code name_too_long_ec =
- std::make_error_code(std::errc::filename_too_long);
-
- struct TestCase {
- path p;
- std::error_code expect_ec;
- } const TestCases[] = {
- {file, perm_ec},
- {sym, perm_ec},
- {path(std::string(2500, 'a')), name_too_long_ec}
- };
- for (auto& TC : TestCases)
- {
- { // test non-throwing case
- std::error_code ec = set_ec;
- file_status st = status(TC.p, ec);
- TEST_CHECK(ec == TC.expect_ec);
- TEST_CHECK(st.type() == file_type::none);
- TEST_CHECK(st.permissions() == perms::unknown);
- }
-#ifndef TEST_HAS_NO_EXCEPTIONS
- { // test throwing case
- try {
- status(TC.p);
- } catch (filesystem_error const& err) {
- TEST_CHECK(err.path1() == TC.p);
- TEST_CHECK(err.path2() == "");
- TEST_CHECK(err.code() == TC.expect_ec);
- }
- }
-#endif
- }
-}
-
-TEST_CASE(status_file_types_test)
-{
- scoped_test_env env;
- struct TestCase {
- path p;
- file_type expect_type;
- } cases[] = {
- {StaticEnv::File, file_type::regular},
- {StaticEnv::SymlinkToFile, file_type::regular},
- {StaticEnv::Dir, file_type::directory},
- {StaticEnv::SymlinkToDir, file_type::directory},
- // Block files tested elsewhere
- {StaticEnv::CharFile, file_type::character},
-#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets
- {env.create_socket("socket"), file_type::socket},
-#endif
- {env.create_fifo("fifo"), file_type::fifo}
- };
- for (const auto& TC : cases) {
- // test non-throwing case
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- file_status st = status(TC.p, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(st.type() == TC.expect_type);
- TEST_CHECK(st.permissions() != perms::unknown);
- // test throwing case
- TEST_REQUIRE_NO_THROW(st = status(TC.p));
- TEST_CHECK(st.type() == TC.expect_type);
- TEST_CHECK(st.permissions() != perms::unknown);
- }
-}
-
-TEST_CASE(test_block_file)
-{
- const path possible_paths[] = {
- "/dev/drive0", // Apple
- "/dev/sda",
- "/dev/loop0"
- };
- path p;
- for (const path& possible_p : possible_paths) {
- std::error_code ec;
- if (exists(possible_p, ec)) {
- p = possible_p;
- break;
- }
- }
- if (p == path{}) {
- TEST_UNSUPPORTED();
- }
- // test non-throwing case
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- file_status st = status(p, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(st.type() == file_type::block);
- TEST_CHECK(st.permissions() != perms::unknown);
- // test throwing case
- TEST_REQUIRE_NO_THROW(st = status(p));
- TEST_CHECK(st.type() == file_type::block);
- TEST_CHECK(st.permissions() != perms::unknown);
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// bool status_known(file_status s) noexcept;
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(status_known_test_suite)
-
-TEST_CASE(signature_test)
-{
- file_status s; ((void)s);
- ASSERT_SAME_TYPE(decltype(status_known(s)), bool);
- ASSERT_NOEXCEPT(status_known(s));
-}
-
-TEST_CASE(status_known_test)
-{
- struct TestCase {
- file_type type;
- bool expect;
- };
- const TestCase testCases[] = {
- {file_type::none, false},
- {file_type::not_found, true},
- {file_type::regular, true},
- {file_type::directory, true},
- {file_type::symlink, true},
- {file_type::block, true},
- {file_type::character, true},
- {file_type::fifo, true},
- {file_type::socket, true},
- {file_type::unknown, true}
- };
- for (auto& TC : testCases) {
- file_status s(TC.type);
- TEST_CHECK(status_known(s) == TC.expect);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// file_status symlink_status(const path& p);
-// file_status symlink_status(const path& p, error_code& ec) noexcept;
-
-#include "filesystem_include.hpp"
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-TEST_SUITE(filesystem_symlink_status_test_suite)
-
-TEST_CASE(signature_test)
-{
- const path p; ((void)p);
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(symlink_status(p));
- ASSERT_NOEXCEPT(symlink_status(p, ec));
-}
-
-TEST_CASE(test_symlink_status_not_found)
-{
- const std::error_code expect_ec =
- std::make_error_code(std::errc::no_such_file_or_directory);
- const path cases[] {
- StaticEnv::DNE
- };
- for (auto& p : cases) {
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- // test non-throwing overload.
- file_status st = symlink_status(p, ec);
- TEST_CHECK(ec == expect_ec);
- TEST_CHECK(st.type() == file_type::not_found);
- TEST_CHECK(st.permissions() == perms::unknown);
- // test throwing overload. It should not throw even though it reports
- // that the file was not found.
- TEST_CHECK_NO_THROW(st = status(p));
- TEST_CHECK(st.type() == file_type::not_found);
- TEST_CHECK(st.permissions() == perms::unknown);
- }
-}
-
-TEST_CASE(test_symlink_status_cannot_resolve)
-{
- scoped_test_env env;
- const path dir = env.create_dir("dir");
- const path file_in_dir = env.create_file("dir/file", 42);
- const path sym_in_dir = env.create_symlink("dir/file", "dir/bad_sym");
- const path sym_points_in_dir = env.create_symlink("dir/file", "sym");
- permissions(dir, perms::none);
-
- const std::error_code set_ec =
- std::make_error_code(std::errc::address_in_use);
- const std::error_code expect_ec =
- std::make_error_code(std::errc::permission_denied);
-
- const path fail_cases[] = {
- file_in_dir, sym_in_dir
- };
- for (auto& p : fail_cases)
- {
- { // test non-throwing case
- std::error_code ec = set_ec;
- file_status st = symlink_status(p, ec);
- TEST_CHECK(ec == expect_ec);
- TEST_CHECK(st.type() == file_type::none);
- TEST_CHECK(st.permissions() == perms::unknown);
- }
-#ifndef TEST_HAS_NO_EXCEPTIONS
- { // test throwing case
- try {
- symlink_status(p);
- } catch (filesystem_error const& err) {
- TEST_CHECK(err.path1() == p);
- TEST_CHECK(err.path2() == "");
- TEST_CHECK(err.code() == expect_ec);
- }
- }
-#endif
- }
- // Test that a symlink that points into a directory without read perms
- // can be stat-ed using symlink_status
- {
- std::error_code ec = set_ec;
- file_status st = symlink_status(sym_points_in_dir, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(st.type() == file_type::symlink);
- TEST_CHECK(st.permissions() != perms::unknown);
- // test non-throwing version
- TEST_REQUIRE_NO_THROW(st = symlink_status(sym_points_in_dir));
- TEST_CHECK(st.type() == file_type::symlink);
- TEST_CHECK(st.permissions() != perms::unknown);
- }
-}
-
-
-TEST_CASE(symlink_status_file_types_test)
-{
- scoped_test_env env;
- struct TestCase {
- path p;
- file_type expect_type;
- } cases[] = {
- {StaticEnv::BadSymlink, file_type::symlink},
- {StaticEnv::File, file_type::regular},
- {StaticEnv::SymlinkToFile, file_type::symlink},
- {StaticEnv::Dir, file_type::directory},
- {StaticEnv::SymlinkToDir, file_type::symlink},
- // Block files tested elsewhere
- {StaticEnv::CharFile, file_type::character},
-#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets
- {env.create_socket("socket"), file_type::socket},
-#endif
- {env.create_fifo("fifo"), file_type::fifo}
- };
- for (const auto& TC : cases) {
- // test non-throwing case
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- file_status st = symlink_status(TC.p, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(st.type() == TC.expect_type);
- TEST_CHECK(st.permissions() != perms::unknown);
- // test throwing case
- TEST_REQUIRE_NO_THROW(st = symlink_status(TC.p));
- TEST_CHECK(st.type() == TC.expect_type);
- TEST_CHECK(st.permissions() != perms::unknown);
- }
-}
-
-TEST_CASE(test_block_file)
-{
- const path possible_paths[] = {
- "/dev/drive0", // Apple
- "/dev/sda", // Linux
- "/dev/loop0" // Linux
- // No FreeBSD files known
- };
- path p;
- for (const path& possible_p : possible_paths) {
- std::error_code ec;
- if (exists(possible_p, ec)) {
- p = possible_p;
- break;
- }
- }
- if (p == path{}) {
- TEST_UNSUPPORTED();
- }
- scoped_test_env env;
- { // test block file
- // test non-throwing case
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- file_status st = symlink_status(p, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(st.type() == file_type::block);
- TEST_CHECK(st.permissions() != perms::unknown);
- // test throwing case
- TEST_REQUIRE_NO_THROW(st = symlink_status(p));
- TEST_CHECK(st.type() == file_type::block);
- TEST_CHECK(st.permissions() != perms::unknown);
- }
- const path sym = env.make_env_path("sym");
- create_symlink(p, sym);
- { // test symlink to block file
- // test non-throwing case
- std::error_code ec = std::make_error_code(std::errc::address_in_use);
- file_status st = symlink_status(sym, ec);
- TEST_CHECK(!ec);
- TEST_CHECK(st.type() == file_type::symlink);
- TEST_CHECK(st.permissions() != perms::unknown);
- // test throwing case
- TEST_REQUIRE_NO_THROW(st = symlink_status(sym));
- TEST_CHECK(st.type() == file_type::symlink);
- TEST_CHECK(st.permissions() != perms::unknown);
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path temp_directory_path();
-// path temp_directory_path(error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <memory>
-#include <cstdlib>
-#include <cstring>
-#include <cassert>
-
-#include "test_macros.h"
-#include "rapid-cxx-test.hpp"
-#include "filesystem_test_helper.hpp"
-
-using namespace fs;
-
-void PutEnv(std::string var, std::string value) {
- assert(::setenv(var.c_str(), value.c_str(), /* overwrite */ 1) == 0);
-}
-
-void UnsetEnv(std::string var) {
- assert(::unsetenv(var.c_str()) == 0);
-}
-
-TEST_SUITE(filesystem_temp_directory_path_test_suite)
-
-TEST_CASE(signature_test)
-{
- std::error_code ec; ((void)ec);
- ASSERT_NOT_NOEXCEPT(temp_directory_path());
- ASSERT_NOT_NOEXCEPT(temp_directory_path(ec));
-}
-
-TEST_CASE(basic_tests)
-{
- scoped_test_env env;
- const path dne = env.make_env_path("dne");
- const path file = env.create_file("file", 42);
- const path dir_perms = env.create_dir("bad_perms_dir");
- const path nested_dir = env.create_dir("bad_perms_dir/nested");
- permissions(dir_perms, perms::none);
- const std::error_code expect_ec = std::make_error_code(std::errc::not_a_directory);
- struct TestCase {
- std::string name;
- path p;
- } cases[] = {
- {"TMPDIR", env.create_dir("dir1")},
- {"TMP", env.create_dir("dir2")},
- {"TEMP", env.create_dir("dir3")},
- {"TEMPDIR", env.create_dir("dir4")}
- };
- for (auto& TC : cases) {
- PutEnv(TC.name, TC.p);
- }
- for (auto& TC : cases) {
- std::error_code ec = GetTestEC();
- path ret = temp_directory_path(ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ret == TC.p);
- TEST_CHECK(is_directory(ret));
-
- // Set the env variable to a path that does not exist and check
- // that it fails.
- PutEnv(TC.name, dne);
- ec = GetTestEC();
- ret = temp_directory_path(ec);
- LIBCPP_ONLY(TEST_CHECK(ec == expect_ec));
- TEST_CHECK(ec != GetTestEC());
- TEST_CHECK(ec);
- TEST_CHECK(ret == "");
-
- // Set the env variable to point to a file and check that it fails.
- PutEnv(TC.name, file);
- ec = GetTestEC();
- ret = temp_directory_path(ec);
- LIBCPP_ONLY(TEST_CHECK(ec == expect_ec));
- TEST_CHECK(ec != GetTestEC());
- TEST_CHECK(ec);
- TEST_CHECK(ret == "");
-
- // Set the env variable to point to a dir we can't access
- PutEnv(TC.name, nested_dir);
- ec = GetTestEC();
- ret = temp_directory_path(ec);
- TEST_CHECK(ec == std::make_error_code(std::errc::permission_denied));
- TEST_CHECK(ret == "");
-
- // Set the env variable to point to a non-existent dir
- PutEnv(TC.name, TC.p / "does_not_exist");
- ec = GetTestEC();
- ret = temp_directory_path(ec);
- TEST_CHECK(ec != GetTestEC());
- TEST_CHECK(ec);
- TEST_CHECK(ret == "");
-
- // Finally erase this env variable
- UnsetEnv(TC.name);
- }
- // No env variables are defined
- {
- std::error_code ec = GetTestEC();
- path ret = temp_directory_path(ec);
- TEST_CHECK(!ec);
- TEST_CHECK(ret == "/tmp");
- TEST_CHECK(is_directory(ret));
- }
-}
-
-TEST_SUITE_END()
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is dual licensed under the MIT and the University of Illinois Open
-// Source Licenses. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++98, c++03
-
-// <experimental/filesystem>
-
-// path weakly_canonical(const path& p);
-// path weakly_canonical(const path& p, error_code& ec);
-
-#include "filesystem_include.hpp"
-#include <type_traits>
-#include <vector>
-#include <iostream>
-#include <cassert>
-
-#include "test_macros.h"
-#include "test_iterators.h"
-#include "count_new.hpp"
-#include "filesystem_test_helper.hpp"
-
-
-int main() {
- // clang-format off
- struct {
- std::string input;
- std::string expect;
- } TestCases[] = {
- {"", fs::current_path()},
- {".", fs::current_path()},
- {"/", "/"},
- {"/foo", "/foo"},
- {"/.", "/"},
- {"/./", "/"},
- {"a/b", fs::current_path() / "a/b"},
- {"a", fs::current_path() / "a"},
- {"a/b/", fs::current_path() / "a/b/"},
- {StaticEnv::File, StaticEnv::File},
- {StaticEnv::Dir, StaticEnv::Dir},
- {StaticEnv::SymlinkToDir, StaticEnv::Dir},
- {StaticEnv::SymlinkToDir / "dir2/.", StaticEnv::Dir / "dir2"},
- // FIXME? If the trailing separator occurs in a part of the path that exists,
- // it is ommitted. Otherwise it is added to the end of the result.
- {StaticEnv::SymlinkToDir / "dir2/./", StaticEnv::Dir / "dir2"},
- {StaticEnv::SymlinkToDir / "dir2/DNE/./", StaticEnv::Dir / "dir2/DNE/"},
- {StaticEnv::SymlinkToDir / "dir2", StaticEnv::Dir2},
- {StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/..", StaticEnv::Dir2 / ""},
- {StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2", StaticEnv::Dir2 / "DNE/DNE2"},
- {StaticEnv::Dir / "../dir1", StaticEnv::Dir},
- {StaticEnv::Dir / "./.", StaticEnv::Dir},
- {StaticEnv::Dir / "DNE/../foo", StaticEnv::Dir / "foo"}
- };
- // clang-format on
- int ID = 0;
- bool Failed = false;
- for (auto& TC : TestCases) {
- ++ID;
- fs::path p(TC.input);
- const fs::path output = fs::weakly_canonical(p);
- if (!PathEq(output, TC.expect)) {
- Failed = true;
- std::cerr << "TEST CASE #" << ID << " FAILED: \n";
- std::cerr << " Input: '" << TC.input << "'\n";
- std::cerr << " Expected: '" << TC.expect << "'\n";
- std::cerr << " Output: '" << output.native() << "'";
- std::cerr << std::endl;
- }
- }
- return Failed;
-}
+++ /dev/null
-# Disable all of the filesystem tests if the correct feature is not available.
-if 'c++filesystem' not in config.available_features:
- config.unsupported = True
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// basic_filebuf<charT,traits>* open(const filesystem::path& p, ios_base::openmode mode);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+#include "platform_support.h"
+
+namespace fs = std::filesystem;
+
+int main() {
+
+ fs::path p = get_temp_file_name();
+ {
+ std::filebuf f;
+ assert(f.open(p, std::ios_base::out) != 0);
+ assert(f.is_open());
+ assert(f.sputn("123", 3) == 3);
+ }
+ {
+ std::filebuf f;
+ assert(f.open(p, std::ios_base::in) != 0);
+ assert(f.is_open());
+ assert(f.sbumpc() == '1');
+ assert(f.sbumpc() == '2');
+ assert(f.sbumpc() == '3');
+ }
+ std::remove(p.c_str());
+ {
+ std::wfilebuf f;
+ assert(f.open(p, std::ios_base::out) != 0);
+ assert(f.is_open());
+ assert(f.sputn(L"123", 3) == 3);
+ }
+ {
+ std::wfilebuf f;
+ assert(f.open(p, std::ios_base::in) != 0);
+ assert(f.is_open());
+ assert(f.sbumpc() == L'1');
+ assert(f.sbumpc() == L'2');
+ assert(f.sbumpc() == L'3');
+ }
+ remove(p.c_str());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// plate <class charT, class traits = char_traits<charT> >
+// class basic_fstream
+
+// explicit basic_fstream(const filesystem::path& s,
+// ios_base::openmode mode = ios_base::in|ios_base::out);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+#include "platform_support.h"
+
+namespace fs = std::filesystem;
+
+int main() {
+ fs::path p = get_temp_file_name();
+ {
+ std::fstream fs(p, std::ios_base::in | std::ios_base::out |
+ std::ios_base::trunc);
+ double x = 0;
+ fs << 3.25;
+ fs.seekg(0);
+ fs >> x;
+ assert(x == 3.25);
+ }
+ std::remove(p.c_str());
+ {
+ std::wfstream fs(p, std::ios_base::in | std::ios_base::out |
+ std::ios_base::trunc);
+ double x = 0;
+ fs << 3.25;
+ fs.seekg(0);
+ fs >> x;
+ assert(x == 3.25);
+ }
+ std::remove(p.c_str());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// plate <class charT, class traits = char_traits<charT> >
+// class basic_fstream
+
+// void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in|ios_base::out);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+#include "platform_support.h"
+
+int main() {
+ std::filesystem::path p = get_temp_file_name();
+ {
+ std::fstream stream;
+ assert(!stream.is_open());
+ stream.open(p,
+ std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+ assert(stream.is_open());
+ double x = 0;
+ stream << 3.25;
+ stream.seekg(0);
+ stream >> x;
+ assert(x == 3.25);
+ }
+ std::remove(p.c_str());
+ {
+ std::wfstream stream;
+ assert(!stream.is_open());
+ stream.open(p,
+ std::ios_base::in | std::ios_base::out | std::ios_base::trunc);
+ assert(stream.is_open());
+ double x = 0;
+ stream << 3.25;
+ stream.seekg(0);
+ stream >> x;
+ assert(x == 3.25);
+ }
+ std::remove(p.c_str());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// template <class charT, class traits = char_traits<charT> >
+// class basic_ifstream
+
+// explicit basic_ifstream(const filesystem::path& s,
+// ios_base::openmode mode = ios_base::in);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+
+namespace fs = std::filesystem;
+
+int main() {
+ {
+ fs::path p;
+ static_assert(!std::is_convertible<fs::path, std::ifstream>::value,
+ "ctor should be explicit");
+ static_assert(std::is_constructible<std::ifstream, fs::path const&,
+ std::ios_base::openmode>::value,
+ "");
+ }
+ {
+ std::ifstream fs(fs::path("test.dat"));
+ double x = 0;
+ fs >> x;
+ assert(x == 3.25);
+ }
+ // std::ifstream(const fs::path&, std::ios_base::openmode) is tested in
+ // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
+ // which creates writable files.
+ {
+ std::wifstream fs(fs::path("test.dat"));
+ double x = 0;
+ fs >> x;
+ assert(x == 3.25);
+ }
+ // std::wifstream(const fs::path&, std::ios_base::openmode) is tested in
+ // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp
+ // which creates writable files.
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// template <class charT, class traits = char_traits<charT> >
+// class basic_ifstream
+
+// void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+
+int main() {
+ {
+ std::ifstream fs;
+ assert(!fs.is_open());
+ char c = 'a';
+ fs >> c;
+ assert(fs.fail());
+ assert(c == 'a');
+ fs.open(std::filesystem::path("test.dat"));
+ assert(fs.is_open());
+ fs >> c;
+ assert(c == 'r');
+ }
+ {
+ std::wifstream fs;
+ assert(!fs.is_open());
+ wchar_t c = L'a';
+ fs >> c;
+ assert(fs.fail());
+ assert(c == L'a');
+ fs.open(std::filesystem::path("test.dat"));
+ assert(fs.is_open());
+ fs >> c;
+ assert(c == L'r');
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// plate <class charT, class traits = char_traits<charT> >
+// class basic_ofstream
+
+// explicit basic_ofstream(const filesystem::path& s, ios_base::openmode mode = ios_base::out);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+#include "platform_support.h"
+
+namespace fs = std::filesystem;
+
+int main() {
+ fs::path p = get_temp_file_name();
+ {
+ static_assert(!std::is_convertible<fs::path, std::ofstream>::value,
+ "ctor should be explicit");
+ static_assert(std::is_constructible<std::ofstream, fs::path const&,
+ std::ios_base::openmode>::value,
+ "");
+ }
+ {
+ std::ofstream stream(p);
+ stream << 3.25;
+ }
+ {
+ std::ifstream stream(p);
+ double x = 0;
+ stream >> x;
+ assert(x == 3.25);
+ }
+ {
+ std::ifstream stream(p, std::ios_base::out);
+ double x = 0;
+ stream >> x;
+ assert(x == 3.25);
+ }
+ std::remove(p.c_str());
+ {
+ std::wofstream stream(p);
+ stream << 3.25;
+ }
+ {
+ std::wifstream stream(p);
+ double x = 0;
+ stream >> x;
+ assert(x == 3.25);
+ }
+ {
+ std::wifstream stream(p, std::ios_base::out);
+ double x = 0;
+ stream >> x;
+ assert(x == 3.25);
+ }
+ std::remove(p.c_str());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <fstream>
+
+// plate <class charT, class traits = char_traits<charT> >
+// class basic_ofstream
+
+// void open(const filesystem::path& s, ios_base::openmode mode = ios_base::out);
+
+#include <fstream>
+#include <filesystem>
+#include <cassert>
+#include "platform_support.h"
+
+namespace fs = std::filesystem;
+
+int main() {
+ fs::path p = get_temp_file_name();
+ {
+ std::ofstream fs;
+ assert(!fs.is_open());
+ char c = 'a';
+ fs << c;
+ assert(fs.fail());
+ fs.open(p);
+ assert(fs.is_open());
+ fs << c;
+ }
+ {
+ std::ifstream fs(p.c_str());
+ char c = 0;
+ fs >> c;
+ assert(c == 'a');
+ }
+ std::remove(p.c_str());
+ {
+ std::wofstream fs;
+ assert(!fs.is_open());
+ wchar_t c = L'a';
+ fs << c;
+ assert(fs.fail());
+ fs.open(p);
+ assert(fs.is_open());
+ fs << c;
+ }
+ {
+ std::wifstream fs(p.c_str());
+ wchar_t c = 0;
+ fs >> c;
+ assert(c == L'a');
+ }
+ std::remove(p.c_str());
+}
--- /dev/null
+dne
\ No newline at end of file
--- /dev/null
+dir3
\ No newline at end of file
--- /dev/null
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
--- /dev/null
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
--- /dev/null
+dir1
\ No newline at end of file
--- /dev/null
+empty_file
\ No newline at end of file
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry(const directory_entry&) = default;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+#include "test_convertible.hpp"
+
+TEST_SUITE(directory_entry_path_ctor_suite)
+
+TEST_CASE(copy_ctor) {
+ using namespace fs;
+ // Copy
+ {
+ static_assert(std::is_copy_constructible<directory_entry>::value,
+ "directory_entry must be copy constructible");
+ static_assert(!std::is_nothrow_copy_constructible<directory_entry>::value,
+ "directory_entry's copy constructor cannot be noexcept");
+ const path p("foo/bar/baz");
+ const directory_entry e(p);
+ assert(e.path() == p);
+ directory_entry e2(e);
+ assert(e.path() == p);
+ assert(e2.path() == p);
+ }
+}
+
+TEST_CASE(copy_ctor_copies_cache) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ {
+ directory_entry ent(sym);
+
+ fs::remove(sym);
+
+ directory_entry ent_cp(ent);
+ TEST_CHECK(ent_cp.path() == sym);
+ TEST_CHECK(ent_cp.is_symlink());
+ }
+
+ {
+ directory_entry ent(file);
+
+ fs::remove(file);
+
+ directory_entry ent_cp(ent);
+ TEST_CHECK(ent_cp.path() == file);
+ TEST_CHECK(ent_cp.is_regular_file());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry& operator=(directory_entry const&) = default;
+// directory_entry& operator=(directory_entry&&) noexcept = default;
+// void assign(path const&);
+// void replace_filename(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+TEST_SUITE(directory_entry_ctor_suite)
+
+TEST_CASE(test_copy_assign_operator) {
+ using namespace fs;
+ // Copy
+ {
+ static_assert(std::is_copy_assignable<directory_entry>::value,
+ "directory_entry must be copy assignable");
+ static_assert(!std::is_nothrow_copy_assignable<directory_entry>::value,
+ "directory_entry's copy assignment cannot be noexcept");
+ const path p("foo/bar/baz");
+ const path p2("abc");
+ const directory_entry e(p);
+ directory_entry e2;
+ assert(e.path() == p && e2.path() == path());
+ e2 = e;
+ assert(e.path() == p && e2.path() == p);
+ directory_entry e3(p2);
+ e2 = e3;
+ assert(e2.path() == p2 && e3.path() == p2);
+ }
+}
+
+TEST_CASE(copy_assign_copies_cache) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ {
+ directory_entry ent(sym);
+
+ fs::remove(sym);
+
+ directory_entry ent_cp;
+ ent_cp = ent;
+ TEST_CHECK(ent_cp.path() == sym);
+ TEST_CHECK(ent_cp.is_symlink());
+ }
+
+ {
+ directory_entry ent(file);
+
+ fs::remove(file);
+
+ directory_entry ent_cp;
+ ent_cp = ent;
+ TEST_CHECK(ent_cp.path() == file);
+ TEST_CHECK(ent_cp.is_regular_file());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry() noexcept = default;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+int main() {
+ using namespace fs;
+ // Default
+ {
+ static_assert(std::is_nothrow_default_constructible<directory_entry>::value,
+ "directory_entry must have a nothrow default constructor");
+ directory_entry e;
+ assert(e.path() == path());
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+// XFAIL: apple-clang-7, clang-3.7, clang-3.8
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry() noexcept = default;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+int main() {
+ using namespace fs;
+ // Default
+ {
+ static_assert(std::is_nothrow_default_constructible<directory_entry>::value,
+ "directory_entry must have a nothrow default constructor");
+ const directory_entry e;
+ assert(e.path() == path());
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry(directory_entry&&) noexcept = default;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+#include "test_convertible.hpp"
+
+TEST_SUITE(directory_entry_path_ctor_suite)
+
+TEST_CASE(move_ctor) {
+ using namespace fs;
+ // Move
+ {
+ static_assert(std::is_nothrow_move_constructible<directory_entry>::value,
+ "directory_entry must be nothrow move constructible");
+ const path p("foo/bar/baz");
+ directory_entry e(p);
+ assert(e.path() == p);
+ directory_entry e2(std::move(e));
+ assert(e2.path() == p);
+ assert(e.path() != p); // Testing moved from state.
+ }
+}
+
+TEST_CASE(move_ctor_copies_cache) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ {
+ directory_entry ent(sym);
+
+ fs::remove(sym);
+
+ directory_entry ent_cp(std::move(ent));
+ TEST_CHECK(ent_cp.path() == sym);
+ TEST_CHECK(ent_cp.is_symlink());
+ }
+
+ {
+ directory_entry ent(file);
+
+ fs::remove(file);
+
+ directory_entry ent_cp(std::move(ent));
+ TEST_CHECK(ent_cp.path() == file);
+ TEST_CHECK(ent_cp.is_regular_file());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry& operator=(directory_entry const&) = default;
+// directory_entry& operator=(directory_entry&&) noexcept = default;
+// void assign(path const&);
+// void replace_filename(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+TEST_SUITE(directory_entry_ctor_suite)
+
+TEST_CASE(test_move_assign_operator) {
+ using namespace fs;
+ // Copy
+ {
+ static_assert(std::is_nothrow_move_assignable<directory_entry>::value,
+ "directory_entry is noexcept move assignable");
+ const path p("foo/bar/baz");
+ const path p2("abc");
+ directory_entry e(p);
+ directory_entry e2(p2);
+ assert(e.path() == p && e2.path() == p2);
+ e2 = std::move(e);
+ assert(e2.path() == p);
+ assert(e.path() != p); // testing moved from state
+ }
+}
+
+TEST_CASE(move_assign_copies_cache) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ {
+ directory_entry ent(sym);
+
+ fs::remove(sym);
+
+ directory_entry ent_cp;
+ ent_cp = std::move(ent);
+ TEST_CHECK(ent_cp.path() == sym);
+ TEST_CHECK(ent_cp.is_symlink());
+ }
+
+ {
+ directory_entry ent(file);
+
+ fs::remove(file);
+
+ directory_entry ent_cp;
+ ent_cp = std::move(ent);
+ TEST_CHECK(ent_cp.path() == file);
+ TEST_CHECK(ent_cp.is_regular_file());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// explicit directory_entry(const path);
+// directory_entry(const path&, error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+#include "test_convertible.hpp"
+
+TEST_SUITE(directory_entry_path_ctor_suite)
+
+TEST_CASE(path_ctor) {
+ using namespace fs;
+ {
+ static_assert(std::is_constructible<directory_entry, const path&>::value,
+ "directory_entry must be constructible from path");
+ static_assert(
+ !std::is_nothrow_constructible<directory_entry, const path&>::value,
+ "directory_entry constructor should not be noexcept");
+ static_assert(!std::is_convertible<path const&, directory_entry>::value,
+ "directory_entry constructor should be explicit");
+ }
+ {
+ const path p("foo/bar/baz");
+ const directory_entry e(p);
+ TEST_CHECK(e.path() == p);
+ }
+}
+
+TEST_CASE(path_ec_ctor) {
+ using namespace fs;
+ {
+ static_assert(
+ std::is_constructible<directory_entry, const path&,
+ std::error_code&>::value,
+ "directory_entry must be constructible from path and error_code");
+ static_assert(!std::is_nothrow_constructible<directory_entry, const path&,
+ std::error_code&>::value,
+ "directory_entry constructor should not be noexcept");
+ static_assert(
+ test_convertible<directory_entry, const path&, std::error_code&>(),
+ "directory_entry constructor should not be explicit");
+ }
+ {
+ std::error_code ec = GetTestEC();
+ const directory_entry e(StaticEnv::File, ec);
+ TEST_CHECK(e.path() == StaticEnv::File);
+ TEST_CHECK(!ec);
+ }
+ {
+ const path p("foo/bar/baz");
+ std::error_code ec = GetTestEC();
+ const directory_entry e(p, ec);
+ TEST_CHECK(e.path() == p);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ }
+}
+
+TEST_CASE(path_ctor_calls_refresh) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ {
+ directory_entry ent(file);
+ std::error_code ec = GetTestEC();
+ directory_entry ent_ec(file, ec);
+ TEST_CHECK(!ec);
+
+ LIBCPP_ONLY(remove(file));
+
+ TEST_CHECK(ent.exists());
+ TEST_CHECK(ent_ec.exists());
+
+ TEST_CHECK(ent.file_size() == 42);
+ TEST_CHECK(ent_ec.file_size() == 42);
+ }
+
+ env.create_file("dir/file", 101);
+
+ {
+ directory_entry ent(sym);
+ std::error_code ec = GetTestEC();
+ directory_entry ent_ec(sym, ec);
+ TEST_CHECK(!ec);
+
+ LIBCPP_ONLY(remove(file));
+ LIBCPP_ONLY(remove(sym));
+
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent_ec.is_symlink());
+
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent_ec.is_regular_file());
+
+ TEST_CHECK(ent.file_size() == 101);
+ TEST_CHECK(ent_ec.file_size() == 101);
+ }
+}
+
+TEST_CASE(path_ctor_dne) {
+ using namespace fs;
+
+ {
+ std::error_code ec = GetTestEC();
+ directory_entry ent(StaticEnv::DNE, ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ TEST_CHECK(ent.path() == StaticEnv::DNE);
+ }
+ // don't report dead symlinks as an error.
+ {
+ std::error_code ec = GetTestEC();
+ directory_entry ent(StaticEnv::BadSymlink, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ent.path() == StaticEnv::BadSymlink);
+ }
+ // DNE does not cause the constructor to throw
+ {
+ directory_entry ent(StaticEnv::DNE);
+ TEST_CHECK(ent.path() == StaticEnv::DNE);
+
+ directory_entry ent_two(StaticEnv::BadSymlink);
+ TEST_CHECK(ent_two.path() == StaticEnv::BadSymlink);
+ }
+}
+
+TEST_CASE(path_ctor_cannot_resolve) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file1", 101);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path sym_in_dir = env.create_symlink("dir/file1", "dir/sym2");
+ permissions(dir, perms::none);
+
+ {
+ std::error_code ec = GetTestEC();
+ directory_entry ent(file, ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ TEST_CHECK(ent.path() == file);
+ }
+ {
+ std::error_code ec = GetTestEC();
+ directory_entry ent(sym_in_dir, ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ TEST_CHECK(ent.path() == sym_in_dir);
+ }
+ {
+ std::error_code ec = GetTestEC();
+ directory_entry ent(sym_out_of_dir, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ent.path() == sym_out_of_dir);
+ }
+ {
+ TEST_CHECK_NO_THROW(directory_entry(file));
+ TEST_CHECK_NO_THROW(directory_entry(sym_in_dir));
+ TEST_CHECK_NO_THROW(directory_entry(sym_out_of_dir));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry& operator=(directory_entry const&) = default;
+// directory_entry& operator=(directory_entry&&) noexcept = default;
+// void assign(path const&);
+// void replace_filename(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+TEST_SUITE(directory_entry_mods_suite)
+
+TEST_CASE(test_path_assign_method) {
+ using namespace fs;
+ const path p("foo/bar/baz");
+ const path p2("abc");
+ directory_entry e(p);
+ {
+ static_assert(std::is_same<decltype(e.assign(p)), void>::value,
+ "return type should be void");
+ static_assert(noexcept(e.assign(p)) == false,
+ "operation must not be noexcept");
+ }
+ {
+ TEST_CHECK(e.path() == p);
+ e.assign(p2);
+ TEST_CHECK(e.path() == p2 && e.path() != p);
+ e.assign(p);
+ TEST_CHECK(e.path() == p && e.path() != p2);
+ }
+}
+
+TEST_CASE(test_path_assign_ec_method) {
+ using namespace fs;
+ const path p("foo/bar/baz");
+ const path p2("abc");
+ {
+ std::error_code ec;
+ directory_entry e(p);
+ static_assert(std::is_same<decltype(e.assign(p, ec)), void>::value,
+ "return type should be void");
+ static_assert(noexcept(e.assign(p, ec)) == false,
+ "operation must not be noexcept");
+ }
+ {
+ directory_entry ent(p);
+ std::error_code ec = GetTestEC();
+ ent.assign(p2, ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ TEST_CHECK(ent.path() == p2);
+ }
+}
+
+TEST_CASE(test_assign_calls_refresh) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ {
+ directory_entry ent;
+ ent.assign(file);
+
+ // removing the file demonstrates that the values where cached previously.
+ LIBCPP_ONLY(remove(file));
+
+ TEST_CHECK(ent.is_regular_file());
+ }
+ env.create_file("dir/file", 101);
+ {
+ directory_entry ent;
+ ent.assign(sym);
+
+ LIBCPP_ONLY(remove(file));
+ LIBCPP_ONLY(remove(sym));
+
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ }
+}
+
+TEST_CASE(test_assign_propagates_error) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path file_out_of_dir = env.create_file("file1");
+ const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
+
+ permissions(dir, perms::none);
+
+ {
+ directory_entry ent;
+ std::error_code ec = GetTestEC();
+ ent.assign(file, ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ }
+ {
+ directory_entry ent;
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_in_dir, ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ }
+ {
+ directory_entry ent;
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_out_of_dir, ec);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry& operator=(directory_entry const&) = default;
+// directory_entry& operator=(directory_entry&&) noexcept = default;
+// void assign(path const&);
+// void replace_filename(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+TEST_SUITE(directory_entry_mods_suite)
+
+TEST_CASE(test_refresh_method) {
+ using namespace fs;
+ {
+ directory_entry e;
+ static_assert(noexcept(e.refresh()) == false,
+ "operation cannot be noexcept");
+ static_assert(std::is_same<decltype(e.refresh()), void>::value,
+ "operation must return void");
+ }
+ {
+ directory_entry e;
+ e.refresh();
+ TEST_CHECK(!e.exists());
+ }
+}
+
+TEST_CASE(test_refresh_ec_method) {
+ using namespace fs;
+ {
+ directory_entry e;
+ std::error_code ec;
+ static_assert(noexcept(e.refresh(ec)), "operation should be noexcept");
+ static_assert(std::is_same<decltype(e.refresh(ec)), void>::value,
+ "operation must return void");
+ }
+ {
+ directory_entry e;
+ std::error_code ec = GetTestEC();
+ e.refresh(ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ }
+}
+
+TEST_CASE(refresh_on_file_dne) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+
+ const perms old_perms = status(dir).permissions();
+
+ // test file doesn't exist
+ {
+ directory_entry ent(file);
+ remove(file);
+ TEST_CHECK(ent.exists());
+
+ ent.refresh();
+
+ permissions(dir, perms::none);
+ TEST_CHECK(!ent.exists());
+ }
+ permissions(dir, old_perms);
+ env.create_file("dir/file", 101);
+ {
+ directory_entry ent(file);
+ remove(file);
+ TEST_CHECK(ent.exists());
+
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ permissions(dir, perms::none);
+ TEST_CHECK(!ent.exists());
+ }
+}
+
+void remove_if_exists(const fs::path& p) {
+ std::error_code ec;
+ remove(p, ec);
+}
+
+TEST_CASE(refresh_on_bad_symlink) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+
+ const perms old_perms = status(dir).permissions();
+
+ // test file doesn't exist
+ {
+ directory_entry ent(sym);
+ LIBCPP_ONLY(remove(file));
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.exists());
+
+ remove_if_exists(file);
+ ent.refresh();
+
+ LIBCPP_ONLY(permissions(dir, perms::none));
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(!ent.is_regular_file());
+ TEST_CHECK(!ent.exists());
+ }
+ permissions(dir, old_perms);
+ env.create_file("dir/file", 101);
+ {
+ directory_entry ent(sym);
+ LIBCPP_ONLY(remove(file));
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.exists());
+
+ remove_if_exists(file);
+
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(!ec); // we don't report bad symlinks as an error.
+
+ LIBCPP_ONLY(permissions(dir, perms::none));
+ TEST_CHECK(!ent.exists());
+ }
+}
+
+TEST_CASE(refresh_cannot_resolve) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file1", 99);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
+ perms old_perms = status(dir).permissions();
+
+ {
+ directory_entry ent(file);
+ permissions(dir, perms::none);
+
+ TEST_CHECK(ent.is_regular_file());
+
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ TEST_CHECK(ent.path() == file);
+
+ ExceptionChecker Checker(file, std::errc::permission_denied,
+ "directory_entry::refresh");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh());
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent(sym_in_dir);
+ permissions(dir, perms::none);
+ TEST_CHECK(ent.is_symlink());
+
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ TEST_CHECK(ent.path() == sym_in_dir);
+
+ ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
+ "directory_entry::refresh");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh());
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent(sym_out_of_dir);
+ permissions(dir, perms::none);
+ TEST_CHECK(ent.is_symlink());
+
+ // Failure to resolve the linked entity due to permissions is not
+ // reported as an error.
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ent.is_symlink());
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.exists(ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ TEST_CHECK(ent.path() == sym_out_of_dir);
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent_file(file);
+ directory_entry ent_sym(sym_in_dir);
+ directory_entry ent_sym2(sym_out_of_dir);
+ permissions(dir, perms::none);
+ ((void)ent_file);
+ ((void)ent_sym);
+
+ TEST_CHECK_THROW(filesystem_error, ent_file.refresh());
+ TEST_CHECK_THROW(filesystem_error, ent_sym.refresh());
+ TEST_CHECK_NO_THROW(ent_sym2);
+ }
+}
+
+TEST_CASE(refresh_doesnt_throw_on_dne_but_reports_it) {
+ using namespace fs;
+ scoped_test_env env;
+
+ const path file = env.create_file("file1", 42);
+ const path sym = env.create_symlink("file1", "sym");
+
+ {
+ directory_entry ent(file);
+ TEST_CHECK(ent.file_size() == 42);
+
+ remove(file);
+
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ TEST_CHECK_NO_THROW(ent.refresh());
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ // doesn't throw!
+ TEST_CHECK_THROW(filesystem_error, ent.file_size());
+ }
+ env.create_file("file1", 99);
+ {
+ directory_entry ent(sym);
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.file_size() == 99);
+
+ remove(file);
+
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ TEST_CHECK_THROW(filesystem_error, ent.file_size());
+ }
+}
+
+TEST_CASE(access_cache_after_refresh_fails) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file1", 101);
+ const path sym = env.create_symlink("dir/file", "sym");
+ const path sym_in_dir = env.create_symlink("dir/file", "dir/sym2");
+
+ const perms old_perms = status(dir).permissions();
+
+#define CHECK_ACCESS(func, expect) \
+ ec = GetTestEC(); \
+ TEST_CHECK(ent.func(ec) == expect); \
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied))
+
+ // test file doesn't exist
+ {
+ directory_entry ent(file);
+
+ TEST_CHECK(!ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.exists());
+
+ permissions(dir, perms::none);
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ CHECK_ACCESS(exists, false);
+ CHECK_ACCESS(is_symlink, false);
+ CHECK_ACCESS(last_write_time, file_time_type::min());
+ CHECK_ACCESS(hard_link_count, uintmax_t(-1));
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent(sym_in_dir);
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.exists());
+
+ permissions(dir, perms::none);
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ CHECK_ACCESS(exists, false);
+ CHECK_ACCESS(is_symlink, false);
+ CHECK_ACCESS(last_write_time, file_time_type::min());
+ CHECK_ACCESS(hard_link_count, uintmax_t(-1));
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent(sym);
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.exists());
+
+ permissions(dir, perms::none);
+ std::error_code ec = GetTestEC();
+ ent.refresh(ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ent.is_symlink());
+
+ CHECK_ACCESS(exists, false);
+ CHECK_ACCESS(is_regular_file, false);
+ CHECK_ACCESS(last_write_time, file_time_type::min());
+ CHECK_ACCESS(hard_link_count, uintmax_t(-1));
+ }
+#undef CHECK_ACCESS
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// directory_entry& operator=(directory_entry const&) = default;
+// directory_entry& operator=(directory_entry&&) noexcept = default;
+// void assign(path const&);
+// void replace_filename(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+TEST_SUITE(directory_entry_mods_suite)
+
+TEST_CASE(test_replace_filename_method) {
+ using namespace fs;
+
+ {
+ directory_entry e;
+ path replace;
+ static_assert(noexcept(e.replace_filename(replace)) == false,
+ "operation cannot be noexcept");
+ static_assert(
+ std::is_same<decltype(e.replace_filename(replace)), void>::value,
+ "operation must return void");
+ }
+ {
+ const path p("/path/to/foo.exe");
+ const path replace("bar.out");
+ const path expect("/path/to/bar.out");
+ directory_entry e(p);
+ TEST_CHECK(e.path() == p);
+ e.replace_filename(replace);
+ TEST_CHECK(e.path() == expect);
+ }
+}
+
+TEST_CASE(test_replace_filename_ec_method) {
+ using namespace fs;
+
+ {
+ directory_entry e;
+ path replace;
+ std::error_code ec;
+ static_assert(noexcept(e.replace_filename(replace, ec)) == false,
+ "operation cannot be noexcept");
+ static_assert(
+ std::is_same<decltype(e.replace_filename(replace, ec)), void>::value,
+ "operation must return void");
+ }
+ {
+ const path p("/path/to/foo.exe");
+ const path replace("bar.out");
+ const path expect("/path/to/bar.out");
+ directory_entry e(p);
+ TEST_CHECK(e.path() == p);
+ std::error_code ec = GetTestEC();
+ e.replace_filename(replace, ec);
+ TEST_CHECK(e.path() == expect);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ }
+ {
+ const path p = StaticEnv::EmptyFile;
+ const path expect = StaticEnv::NonEmptyFile;
+ const path replace = StaticEnv::NonEmptyFile.filename();
+ TEST_REQUIRE(expect.parent_path() == p.parent_path());
+ directory_entry e(p);
+ TEST_CHECK(e.path() == p);
+ std::error_code ec = GetTestEC();
+ e.replace_filename(replace, ec);
+ TEST_CHECK(e.path() == expect);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(test_replace_filename_calls_refresh) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_two = env.create_file("dir/file_two", 101);
+ const path sym = env.create_symlink("dir/file", "sym");
+ const path sym_two = env.create_symlink("dir/file_two", "sym_two");
+
+ {
+ directory_entry ent(file);
+ ent.replace_filename(file_two.filename());
+ TEST_REQUIRE(ent.path() == file_two);
+
+ // removing the file demonstrates that the values where cached previously.
+ LIBCPP_ONLY(remove(file_two));
+
+ TEST_CHECK(ent.file_size() == 101);
+ }
+ env.create_file("dir/file_two", 99);
+ {
+ directory_entry ent(sym);
+ ent.replace_filename(sym_two.filename());
+ TEST_REQUIRE(ent.path() == sym_two);
+
+ LIBCPP_ONLY(remove(file_two));
+ LIBCPP_ONLY(remove(sym_two));
+
+ TEST_CHECK(ent.is_symlink());
+ TEST_CHECK(ent.is_regular_file());
+ TEST_CHECK(ent.file_size() == 99);
+ }
+}
+
+TEST_CASE(test_replace_filename_propagates_error) {
+ using namespace fs;
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_two = env.create_file("dir/file_two", 99);
+ const path file_out_of_dir = env.create_file("file_three", 101);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path sym_out_of_dir_two = env.create_symlink("dir/file", "sym_two");
+ const path sym_in_dir = env.create_symlink("file_two", "dir/sym_three");
+ const path sym_in_dir_two = env.create_symlink("file_two", "dir/sym_four");
+
+ const perms old_perms = status(dir).permissions();
+
+ {
+ directory_entry ent(file);
+ permissions(dir, perms::none);
+ std::error_code ec = GetTestEC();
+ ent.replace_filename(file_two.filename(), ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent(sym_in_dir);
+ permissions(dir, perms::none);
+ std::error_code ec = GetTestEC();
+ ent.replace_filename(sym_in_dir_two.filename(), ec);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ }
+ permissions(dir, old_perms);
+ {
+ directory_entry ent(sym_out_of_dir);
+ permissions(dir, perms::none);
+ std::error_code ec = GetTestEC();
+ ent.replace_filename(sym_out_of_dir_two.filename(), ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ent.is_symlink());
+ ec = GetTestEC();
+ TEST_CHECK(!ent.exists(ec));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// bool operator==(directory_entry const&) const noexcept;
+// bool operator!=(directory_entry const&) const noexcept;
+// bool operator< (directory_entry const&) const noexcept;
+// bool operator<=(directory_entry const&) const noexcept;
+// bool operator> (directory_entry const&) const noexcept;
+// bool operator>=(directory_entry const&) const noexcept;
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+
+#define CHECK_OP(Op) \
+ static_assert(std::is_same<decltype(ce. operator Op (ce)), bool>::value, ""); \
+ static_assert(noexcept(ce.operator Op (ce)), "Operation must be noexcept" )
+
+void test_comparison_signatures() {
+ using namespace fs;
+ path const p("foo/bar/baz");
+ // Check that the operators are member functions with the correct signatures.
+ {
+ directory_entry const ce(p);
+ CHECK_OP(==);
+ CHECK_OP(!=);
+ CHECK_OP(< );
+ CHECK_OP(<=);
+ CHECK_OP(> );
+ CHECK_OP(>=);
+ }
+}
+#undef CHECK_OP
+
+// The actual semantics of the comparisons are testing via paths operators.
+void test_comparisons_simple() {
+ using namespace fs;
+ typedef std::pair<path, path> TestType;
+ TestType TestCases[] =
+ {
+ {"", ""},
+ {"", "a"},
+ {"a", "a"},
+ {"a", "b"},
+ {"foo/bar/baz", "foo/bar/baz/"}
+ };
+ auto TestFn = [](path const& LHS, const directory_entry& LHSE,
+ path const& RHS, const directory_entry& RHSE) {
+ assert((LHS == RHS) == (LHSE == RHSE));
+ assert((LHS != RHS) == (LHSE != RHSE));
+ assert((LHS < RHS) == (LHSE < RHSE));
+ assert((LHS <= RHS) == (LHSE <= RHSE));
+ assert((LHS > RHS) == (LHSE > RHSE));
+ assert((LHS >= RHS) == (LHSE >= RHSE));
+ };
+ for (auto const& TC : TestCases) {
+ const directory_entry L(TC.first);
+ const directory_entry R(TC.second);
+ TestFn(TC.first, L, TC.second, R);
+ TestFn(TC.second, R, TC.first, L);
+ }
+}
+
+int main() {
+ test_comparison_signatures();
+ test_comparisons_simple();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// uintmax_t file_size() const;
+// uintmax_t file_size(error_code const&) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "filesystem_test_helper.hpp"
+#include "rapid-cxx-test.hpp"
+
+#include <iostream>
+
+TEST_SUITE(directory_entry_obs_testsuite)
+
+TEST_CASE(signatures) {
+ using namespace fs;
+ {
+ const fs::directory_entry e = {};
+ std::error_code ec;
+ static_assert(std::is_same<decltype(e.file_size()), uintmax_t>::value, "");
+ static_assert(std::is_same<decltype(e.file_size(ec)), uintmax_t>::value,
+ "");
+ static_assert(noexcept(e.file_size()) == false, "");
+ static_assert(noexcept(e.file_size(ec)) == true, "");
+ }
+}
+
+TEST_CASE(basic) {
+ using namespace fs;
+
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+ const path sym = env.create_symlink("file", "sym");
+
+ {
+ directory_entry ent(file);
+ uintmax_t expect = file_size(ent);
+ TEST_CHECK(expect == 42);
+
+ // Remove the file to show that the results were already in the cache.
+ LIBCPP_ONLY(remove(file));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == expect);
+ TEST_CHECK(!ec);
+ }
+ env.create_file("file", 99);
+ {
+ directory_entry ent(sym);
+
+ uintmax_t expect = file_size(ent);
+ TEST_CHECK(expect == 99);
+
+ LIBCPP_ONLY(remove(ent));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == 99);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(not_regular_file) {
+ using namespace fs;
+
+ scoped_test_env env;
+ struct {
+ const path p;
+ std::errc expected_err;
+ } TestCases[] = {
+ {env.create_dir("dir"), std::errc::is_a_directory},
+ {env.create_fifo("fifo"), std::errc::not_supported},
+ {env.create_symlink("dir", "sym"), std::errc::is_a_directory}};
+
+ for (auto const& TC : TestCases) {
+ const path& p = TC.p;
+ directory_entry ent(p);
+ TEST_CHECK(ent.path() == p);
+ std::error_code ec = GetTestEC(0);
+
+ std::error_code other_ec = GetTestEC(1);
+ uintmax_t expect = file_size(p, other_ec);
+
+ uintmax_t got = ent.file_size(ec);
+ TEST_CHECK(got == expect);
+ TEST_CHECK(got == uintmax_t(-1));
+ TEST_CHECK(ec == other_ec);
+ TEST_CHECK(ErrorIs(ec, TC.expected_err));
+
+ ExceptionChecker Checker(p, TC.expected_err, "directory_entry::file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
+ }
+}
+
+TEST_CASE(error_reporting) {
+ using namespace fs;
+
+ scoped_test_env env;
+
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file2", 101);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
+
+ const perms old_perms = status(dir).permissions();
+
+ // test a file which doesn't exist
+ {
+ directory_entry ent;
+
+ std::error_code ec = GetTestEC();
+ ent.assign(StaticEnv::DNE, ec);
+ TEST_REQUIRE(ent.path() == StaticEnv::DNE);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ExceptionChecker Checker(StaticEnv::DNE,
+ std::errc::no_such_file_or_directory,
+ "directory_entry::file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
+ }
+ // test a dead symlink
+ {
+ directory_entry ent;
+
+ std::error_code ec = GetTestEC();
+ uintmax_t expect_bad = file_size(StaticEnv::BadSymlink, ec);
+ TEST_CHECK(expect_bad == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ec = GetTestEC();
+ ent.assign(StaticEnv::BadSymlink, ec);
+ TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == expect_bad);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ExceptionChecker Checker(StaticEnv::BadSymlink,
+ std::errc::no_such_file_or_directory,
+ "directory_entry::file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
+ }
+ // test a file w/o appropriate permissions.
+ {
+ directory_entry ent;
+ uintmax_t expect_good = file_size(file);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(file, ec);
+ TEST_REQUIRE(ent.path() == file);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(file, std::errc::permission_denied, "file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.file_size());
+ }
+ permissions(dir, old_perms);
+ // test a symlink w/o appropriate permissions.
+ {
+ directory_entry ent;
+ uintmax_t expect_good = file_size(sym_in_dir);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_in_dir, ec);
+ TEST_REQUIRE(ent.path() == sym_in_dir);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
+ "file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.file_size());
+ }
+ permissions(dir, old_perms);
+ // test a symlink to a file w/o appropriate permissions
+ {
+ directory_entry ent;
+ uintmax_t expect_good = file_size(sym_out_of_dir);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_out_of_dir, ec);
+ TEST_REQUIRE(ent.path() == sym_out_of_dir);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
+ "file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.file_size(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.file_size());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// file_status status() const;
+// file_status status(error_code const&) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "filesystem_test_helper.hpp"
+#include "rapid-cxx-test.hpp"
+
+TEST_SUITE(directory_entry_obs_testsuite)
+
+TEST_CASE(file_dne) {
+ using namespace fs;
+ directory_entry p("dne");
+}
+
+TEST_CASE(signatures) {
+ using namespace fs;
+ const directory_entry e = {};
+ std::error_code ec;
+#define TEST_FUNC(name) \
+ static_assert(std::is_same<decltype(e.name()), bool>::value, \
+ "wrong return type"); \
+ static_assert(noexcept(e.name()) == false, "should not be noexcept"); \
+ static_assert(std::is_same<decltype(e.name(ec)), bool>::value, \
+ "wrong return type"); \
+ static_assert(noexcept(e.name(ec)) == true, "should be noexcept")
+
+ TEST_FUNC(exists);
+ TEST_FUNC(is_block_file);
+ TEST_FUNC(is_character_file);
+ TEST_FUNC(is_directory);
+ TEST_FUNC(is_fifo);
+ TEST_FUNC(is_other);
+ TEST_FUNC(is_regular_file);
+ TEST_FUNC(is_socket);
+ TEST_FUNC(is_symlink);
+
+#undef TEST_FUNC
+}
+
+TEST_CASE(test_without_ec) {
+ using namespace fs;
+ using fs::directory_entry;
+ using fs::file_status;
+ using fs::path;
+
+ scoped_test_env env;
+ path f = env.create_file("foo", 42);
+ path d = env.create_dir("dir");
+ path fifo = env.create_fifo("fifo");
+ path hl = env.create_hardlink("foo", "hl");
+ for (auto p : {hl, f, d, fifo}) {
+ directory_entry e(p);
+ file_status st = status(p);
+ file_status sym_st = symlink_status(p);
+ fs::remove(p);
+ TEST_REQUIRE(e.exists());
+ TEST_REQUIRE(!exists(p));
+ TEST_CHECK(e.exists() == exists(st));
+ TEST_CHECK(e.is_block_file() == is_block_file(st));
+ TEST_CHECK(e.is_character_file() == is_character_file(st));
+ TEST_CHECK(e.is_directory() == is_directory(st));
+ TEST_CHECK(e.is_fifo() == is_fifo(st));
+ TEST_CHECK(e.is_other() == is_other(st));
+ TEST_CHECK(e.is_regular_file() == is_regular_file(st));
+ TEST_CHECK(e.is_socket() == is_socket(st));
+ TEST_CHECK(e.is_symlink() == is_symlink(sym_st));
+ }
+}
+
+TEST_CASE(test_with_ec) {
+ using namespace fs;
+ using fs::directory_entry;
+ using fs::file_status;
+ using fs::path;
+
+ scoped_test_env env;
+ path f = env.create_file("foo", 42);
+ path d = env.create_dir("dir");
+ path fifo = env.create_fifo("fifo");
+ path hl = env.create_hardlink("foo", "hl");
+ for (auto p : {hl, f, d, fifo}) {
+ directory_entry e(p);
+ std::error_code status_ec = GetTestEC();
+ std::error_code sym_status_ec = GetTestEC(1);
+ file_status st = status(p, status_ec);
+ file_status sym_st = symlink_status(p, sym_status_ec);
+ fs::remove(p);
+ std::error_code ec = GetTestEC(2);
+ auto CheckEC = [&](std::error_code const& other_ec) {
+ bool res = ec == other_ec;
+ ec = GetTestEC(2);
+ return res;
+ };
+
+ TEST_REQUIRE(e.exists(ec));
+ TEST_CHECK(CheckEC(status_ec));
+ TEST_REQUIRE(!exists(p));
+
+ TEST_CHECK(e.exists(ec) == exists(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_directory(ec) == is_directory(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_other(ec) == is_other(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_socket(ec) == is_socket(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
+ TEST_CHECK(CheckEC(sym_status_ec));
+ }
+}
+
+TEST_CASE(test_with_ec_dne) {
+ using namespace fs;
+ using fs::directory_entry;
+ using fs::file_status;
+ using fs::path;
+
+ for (auto p : {StaticEnv::DNE, StaticEnv::BadSymlink}) {
+
+ directory_entry e(p);
+ std::error_code status_ec = GetTestEC();
+ std::error_code sym_status_ec = GetTestEC(1);
+ file_status st = status(p, status_ec);
+ file_status sym_st = symlink_status(p, sym_status_ec);
+ std::error_code ec = GetTestEC(2);
+ auto CheckEC = [&](std::error_code const& other_ec) {
+ bool res = ec == other_ec;
+ ec = GetTestEC(2);
+ return res;
+ };
+
+ TEST_CHECK(e.exists(ec) == exists(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_directory(ec) == is_directory(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_other(ec) == is_other(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_socket(ec) == is_socket(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
+ TEST_CHECK(CheckEC(sym_status_ec));
+ }
+}
+
+TEST_CASE(test_with_ec_cannot_resolve) {
+ using namespace fs;
+ using fs::directory_entry;
+ using fs::file_status;
+ using fs::path;
+
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file2", 99);
+ const path sym = env.create_symlink("file2", "dir/sym");
+
+ perms old_perms = fs::status(dir).permissions();
+
+ for (auto p : {file, sym}) {
+ permissions(dir, old_perms);
+ directory_entry e(p);
+
+ permissions(dir, perms::none);
+ std::error_code dummy_ec;
+ e.refresh(dummy_ec);
+ TEST_REQUIRE(dummy_ec);
+
+ std::error_code status_ec = GetTestEC();
+ std::error_code sym_status_ec = GetTestEC(1);
+ file_status st = status(p, status_ec);
+ file_status sym_st = symlink_status(p, sym_status_ec);
+ std::error_code ec = GetTestEC(2);
+ auto CheckEC = [&](std::error_code const& other_ec) {
+ bool res = ec == other_ec;
+ ec = GetTestEC(2);
+ return res;
+ };
+
+ TEST_CHECK(e.exists(ec) == exists(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_directory(ec) == is_directory(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_other(ec) == is_other(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_socket(ec) == is_socket(st));
+ TEST_CHECK(CheckEC(status_ec));
+
+ TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
+ TEST_CHECK(CheckEC(sym_status_ec));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// uintmax_t hard_link_count() const;
+// uintmax_t hard_link_count(error_code const&) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "filesystem_test_helper.hpp"
+#include "rapid-cxx-test.hpp"
+
+TEST_SUITE(directory_entry_obs_testsuite)
+
+TEST_CASE(signatures) {
+ using namespace fs;
+ {
+ const directory_entry e = {};
+ std::error_code ec;
+ static_assert(std::is_same<decltype(e.hard_link_count()), uintmax_t>::value, "");
+ static_assert(std::is_same<decltype(e.hard_link_count(ec)), uintmax_t>::value,
+ "");
+ static_assert(noexcept(e.hard_link_count()) == false, "");
+ static_assert(noexcept(e.hard_link_count(ec)) == true, "");
+ }
+}
+
+TEST_CASE(basic) {
+ using namespace fs;
+
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+ const path sym = env.create_symlink("file", "sym");
+
+ {
+ directory_entry ent(file);
+ uintmax_t expect = hard_link_count(ent);
+
+ // Remove the file to show that the results were already in the cache.
+ LIBCPP_ONLY(remove(file));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect);
+ TEST_CHECK(!ec);
+ }
+ {
+ directory_entry ent(dir);
+ uintmax_t expect = hard_link_count(ent);
+
+ LIBCPP_ONLY(remove(dir));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect);
+ TEST_CHECK(!ec);
+ }
+ env.create_file("file", 99);
+ env.create_hardlink("file", "hl");
+ {
+ directory_entry ent(sym);
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == 2);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(not_regular_file) {
+ using namespace fs;
+
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dir2 = env.create_dir("dir/dir2");
+ const path fifo = env.create_fifo("dir/fifo");
+ const path sym_to_fifo = env.create_symlink("dir/fifo", "dir/sym");
+
+ const perms old_perms = status(dir).permissions();
+
+ for (auto p : {dir2, fifo, sym_to_fifo}) {
+ permissions(dir, old_perms);
+ std::error_code dummy_ec = GetTestEC();
+ directory_entry ent(p, dummy_ec);
+ TEST_CHECK(!dummy_ec);
+
+ uintmax_t expect = hard_link_count(p);
+
+ LIBCPP_ONLY(permissions(dir, perms::none));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.hard_link_count());
+ }
+}
+
+TEST_CASE(error_reporting) {
+ using namespace fs;
+
+ scoped_test_env env;
+
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file2", 101);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
+
+ const perms old_perms = status(dir).permissions();
+
+ // test a file which doesn't exist
+ {
+ directory_entry ent;
+
+ std::error_code ec = GetTestEC();
+ ent.assign(StaticEnv::DNE, ec);
+ TEST_CHECK(ec);
+ TEST_REQUIRE(ent.path() == StaticEnv::DNE);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ExceptionChecker Checker(StaticEnv::DNE,
+ std::errc::no_such_file_or_directory,
+ "directory_entry::hard_link_count");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
+ }
+ // test a dead symlink
+ {
+ directory_entry ent;
+
+ std::error_code ec = GetTestEC();
+ uintmax_t expect_bad = hard_link_count(StaticEnv::BadSymlink, ec);
+ TEST_CHECK(expect_bad == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ec = GetTestEC();
+ ent.assign(StaticEnv::BadSymlink, ec);
+ TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect_bad);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ExceptionChecker Checker(StaticEnv::BadSymlink,
+ std::errc::no_such_file_or_directory,
+ "directory_entry::hard_link_count");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
+ }
+ // test a file w/o appropriate permissions.
+ {
+ directory_entry ent;
+ uintmax_t expect_good = hard_link_count(file);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(file, ec);
+ TEST_REQUIRE(ent.path() == file);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(file, std::errc::permission_denied,
+ "hard_link_count");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.hard_link_count());
+ }
+ permissions(dir, old_perms);
+ // test a symlink w/o appropriate permissions.
+ {
+ directory_entry ent;
+ uintmax_t expect_good = hard_link_count(sym_in_dir);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_in_dir, ec);
+ TEST_REQUIRE(ent.path() == sym_in_dir);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
+ "hard_link_count");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.hard_link_count());
+ }
+ permissions(dir, old_perms);
+ // test a symlink to a file w/o appropriate permissions
+ {
+ directory_entry ent;
+ uintmax_t expect_good = hard_link_count(sym_out_of_dir);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_out_of_dir, ec);
+ TEST_REQUIRE(ent.path() == sym_out_of_dir);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
+ "hard_link_count");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.hard_link_count(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.hard_link_count());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// file_time_type last_write_time() const;
+// file_time_type last_write_time(error_code const&) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "filesystem_test_helper.hpp"
+#include "rapid-cxx-test.hpp"
+
+TEST_SUITE(directory_entry_obs_testsuite)
+
+TEST_CASE(signatures) {
+ using namespace fs;
+ {
+ const fs::directory_entry e = {};
+ std::error_code ec;
+ static_assert(std::is_same<decltype(e.last_write_time()), file_time_type>::value,
+ "");
+ static_assert(std::is_same<decltype(e.last_write_time(ec)), file_time_type>::value,
+ "");
+ static_assert(noexcept(e.last_write_time()) == false, "");
+ static_assert(noexcept(e.last_write_time(ec)) == true, "");
+ }
+}
+
+TEST_CASE(basic) {
+ using namespace fs;
+
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+ const path sym = env.create_symlink("file", "sym");
+
+ {
+ directory_entry ent(file);
+ file_time_type expect = last_write_time(ent);
+
+ // Remove the file to show that the results were already in the cache.
+ LIBCPP_ONLY(remove(file));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect);
+ TEST_CHECK(!ec);
+ }
+ {
+ directory_entry ent(dir);
+ file_time_type expect = last_write_time(ent);
+
+ LIBCPP_ONLY(remove(dir));
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect);
+ TEST_CHECK(!ec);
+ }
+ env.create_file("file", 99);
+ {
+ directory_entry ent(sym);
+ file_time_type expect = last_write_time(sym);
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(error_reporting) {
+ using namespace fs;
+
+ scoped_test_env env;
+
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path file_out_of_dir = env.create_file("file2", 101);
+ const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
+ const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
+
+ const perms old_perms = status(dir).permissions();
+
+ // test a file which doesn't exist
+ {
+ directory_entry ent;
+
+ std::error_code ec = GetTestEC();
+ ent.assign(StaticEnv::DNE, ec);
+ TEST_REQUIRE(ent.path() == StaticEnv::DNE);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ExceptionChecker Checker(StaticEnv::DNE,
+ std::errc::no_such_file_or_directory,
+ "directory_entry::last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
+ }
+ // test a dead symlink
+ {
+ directory_entry ent;
+
+ std::error_code ec = GetTestEC();
+ file_time_type expect_bad = last_write_time(StaticEnv::BadSymlink, ec);
+ TEST_CHECK(expect_bad == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ec = GetTestEC();
+ ent.assign(StaticEnv::BadSymlink, ec);
+ TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect_bad);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+
+ ExceptionChecker Checker(StaticEnv::BadSymlink,
+ std::errc::no_such_file_or_directory,
+ "directory_entry::last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
+ }
+ // test a file w/o appropriate permissions.
+ {
+ directory_entry ent;
+ file_time_type expect_good = last_write_time(file);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(file, ec);
+ TEST_REQUIRE(ent.path() == file);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(file, std::errc::permission_denied,
+ "last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.last_write_time());
+ }
+ permissions(dir, old_perms);
+ // test a symlink w/o appropriate permissions.
+ {
+ directory_entry ent;
+ file_time_type expect_good = last_write_time(sym_in_dir);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_in_dir, ec);
+ TEST_REQUIRE(ent.path() == sym_in_dir);
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
+ "last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.last_write_time());
+ }
+ permissions(dir, old_perms);
+ // test a symlink to a file w/o appropriate permissions
+ {
+ directory_entry ent;
+ file_time_type expect_good = last_write_time(sym_out_of_dir);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ ent.assign(sym_out_of_dir, ec);
+ TEST_REQUIRE(ent.path() == sym_out_of_dir);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
+ "last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
+
+ permissions(dir, old_perms);
+ ec = GetTestEC();
+ TEST_CHECK(ent.last_write_time(ec) == expect_good);
+ TEST_CHECK(!ec);
+ TEST_CHECK_NO_THROW(ent.last_write_time());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// const path& path() const noexcept;
+// operator const path&() const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+
+void test_path_method() {
+ using namespace fs;
+ const path p("foo/bar/baz.exe");
+ const path p2("abc");
+ {
+ directory_entry nce;
+ const directory_entry e("");
+ static_assert(std::is_same<decltype(e.path()), const path&>::value, "");
+ static_assert(std::is_same<decltype(nce.path()), const path&>::value, "");
+ static_assert(noexcept(e.path()) && noexcept(nce.path()), "");
+ }
+ {
+ directory_entry e(p);
+ path const& pref = e.path();
+ assert(pref == p);
+ assert(&pref == &e.path());
+ e.assign(p2);
+ assert(pref == p2);
+ assert(&pref == &e.path());
+ }
+}
+
+void test_path_conversion() {
+ using namespace fs;
+ const path p("foo/bar/baz.exe");
+ const path p2("abc");
+ {
+ directory_entry nce;
+ const directory_entry e("");
+ // Check conversions exist
+ static_assert(std::is_convertible<directory_entry&, path const&>::value, "");
+ static_assert(std::is_convertible<directory_entry const&, path const&>::value, "");
+ static_assert(std::is_convertible<directory_entry &&, path const&>::value, "");
+ static_assert(std::is_convertible<directory_entry const&&, path const&>::value, "");
+ // Not convertible to non-const
+ static_assert(!std::is_convertible<directory_entry&, path&>::value, "");
+ static_assert(!std::is_convertible<directory_entry const&, path&>::value, "");
+ static_assert(!std::is_convertible<directory_entry &&, path&>::value, "");
+ static_assert(!std::is_convertible<directory_entry const&&, path&>::value, "");
+ // conversions are noexcept
+ static_assert(noexcept(e.operator fs::path const&()) &&
+ noexcept(e.operator fs::path const&()), "");
+ }
+ // const
+ {
+ directory_entry const e(p);
+ path const& pref = e;
+ assert(&pref == &e.path());
+ }
+ // non-const
+ {
+ directory_entry e(p);
+ path const& pref = e;
+ assert(&pref == &e.path());
+
+ e.assign(p2);
+ assert(pref == p2);
+ assert(&pref == &e.path());
+ }
+}
+
+int main() {
+ test_path_method();
+ test_path_conversion();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// file_status status() const;
+// file_status status(error_code const&) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "filesystem_test_helper.hpp"
+#include "rapid-cxx-test.hpp"
+
+TEST_SUITE(directory_entry_status_testsuite)
+
+TEST_CASE(test_basic) {
+ using namespace fs;
+ {
+ const fs::directory_entry e("foo");
+ std::error_code ec;
+ static_assert(std::is_same<decltype(e.status()), fs::file_status>::value, "");
+ static_assert(std::is_same<decltype(e.status(ec)), fs::file_status>::value, "");
+ static_assert(noexcept(e.status()) == false, "");
+ static_assert(noexcept(e.status(ec)) == true, "");
+ }
+ path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile,
+ StaticEnv::DNE};
+ for (const auto& p : TestCases) {
+ const directory_entry e(p);
+ std::error_code pec = GetTestEC(), eec = GetTestEC(1);
+ file_status ps = fs::status(p, pec);
+ file_status es = e.status(eec);
+ TEST_CHECK(ps.type() == es.type());
+ TEST_CHECK(ps.permissions() == es.permissions());
+ TEST_CHECK(pec == eec);
+ }
+ for (const auto& p : TestCases) {
+ const directory_entry e(p);
+ file_status ps = fs::status(p);
+ file_status es = e.status();
+ TEST_CHECK(ps.type() == es.type());
+ TEST_CHECK(ps.permissions() == es.permissions());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_entry
+
+// file_status symlink_status() const;
+// file_status symlink_status(error_code&) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "filesystem_test_helper.hpp"
+#include "rapid-cxx-test.hpp"
+
+TEST_SUITE(directory_entry_obs_suite)
+
+TEST_CASE(test_signature) {
+ using namespace fs;
+ {
+ const directory_entry e("foo");
+ std::error_code ec;
+ static_assert(std::is_same<decltype(e.symlink_status()), file_status>::value, "");
+ static_assert(std::is_same<decltype(e.symlink_status(ec)), file_status>::value, "");
+ static_assert(noexcept(e.symlink_status()) == false, "");
+ static_assert(noexcept(e.symlink_status(ec)) == true, "");
+ }
+ path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile,
+ StaticEnv::DNE};
+ for (const auto& p : TestCases) {
+ const directory_entry e(p);
+ std::error_code pec = GetTestEC(), eec = GetTestEC(1);
+ file_status ps = fs::symlink_status(p, pec);
+ file_status es = e.symlink_status(eec);
+ TEST_CHECK(ps.type() == es.type());
+ TEST_CHECK(ps.permissions() == es.permissions());
+ TEST_CHECK(pec == eec);
+ }
+ for (const auto& p : TestCases) {
+ const directory_entry e(p);
+ file_status ps = fs::symlink_status(p);
+ file_status es = e.symlink_status();
+ TEST_CHECK(ps.type() == es.type());
+ TEST_CHECK(ps.permissions() == es.permissions());
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator(directory_iterator const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_copy_construct_tests)
+
+TEST_CASE(test_constructor_signature)
+{
+ using D = directory_iterator;
+ static_assert(std::is_copy_constructible<D>::value, "");
+}
+
+TEST_CASE(test_copy_end_iterator)
+{
+ const directory_iterator endIt;
+ directory_iterator it(endIt);
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(test_copy_valid_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+ const directory_iterator endIt{};
+
+ const directory_iterator it(testDir);
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+
+ const directory_iterator it2(it);
+ TEST_REQUIRE(it2 == it);
+ TEST_CHECK(*it2 == entry);
+ TEST_CHECK(*it == entry);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator& operator=(directory_iterator const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_copy_assign_tests)
+
+TEST_CASE(test_assignment_signature)
+{
+ using D = directory_iterator;
+ static_assert(std::is_copy_assignable<D>::value, "");
+}
+
+TEST_CASE(test_copy_to_end_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+
+ const directory_iterator from(testDir);
+ TEST_REQUIRE(from != directory_iterator{});
+ const path entry = *from;
+
+ directory_iterator to{};
+ to = from;
+ TEST_REQUIRE(to == from);
+ TEST_CHECK(*to == entry);
+ TEST_CHECK(*from == entry);
+}
+
+
+TEST_CASE(test_copy_from_end_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+
+ const directory_iterator from{};
+
+ directory_iterator to(testDir);
+ TEST_REQUIRE(to != directory_iterator{});
+
+ to = from;
+ TEST_REQUIRE(to == from);
+ TEST_CHECK(to == directory_iterator{});
+}
+
+TEST_CASE(test_copy_valid_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+ const directory_iterator endIt{};
+
+ directory_iterator it_obj(testDir);
+ const directory_iterator& it = it_obj;
+ TEST_REQUIRE(it != endIt);
+ ++it_obj;
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+
+ directory_iterator it2(testDir);
+ TEST_REQUIRE(it2 != it);
+ const path entry2 = *it2;
+ TEST_CHECK(entry2 != entry);
+
+ it2 = it;
+ TEST_REQUIRE(it2 == it);
+ TEST_CHECK(*it2 == entry);
+}
+
+TEST_CASE(test_returns_reference_to_self)
+{
+ const directory_iterator it;
+ directory_iterator it2;
+ directory_iterator& ref = (it2 = it);
+ TEST_CHECK(&ref == &it2);
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// explicit directory_iterator(const path& p);
+// directory_iterator(const path& p, directory_options options);
+// directory_iterator(const path& p, error_code& ec);
+// directory_iterator(const path& p, directory_options options, error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_constructor_tests)
+
+TEST_CASE(test_constructor_signatures)
+{
+ using D = directory_iterator;
+
+ // explicit directory_iterator(path const&);
+ static_assert(!std::is_convertible<path, D>::value, "");
+ static_assert(std::is_constructible<D, path>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path>::value, "");
+
+ // directory_iterator(path const&, error_code&)
+ static_assert(std::is_constructible<D, path,
+ std::error_code&>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path,
+ std::error_code&>::value, "");
+
+ // directory_iterator(path const&, directory_options);
+ static_assert(std::is_constructible<D, path, directory_options>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
+
+ // directory_iterator(path const&, directory_options, error_code&)
+ static_assert(std::is_constructible<D, path, directory_options,
+ std::error_code&>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path, directory_options,
+ std::error_code&>::value, "");
+
+}
+
+TEST_CASE(test_construction_from_bad_path)
+{
+ std::error_code ec;
+ directory_options opts = directory_options::none;
+ const directory_iterator endIt;
+
+ const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink };
+ for (path const& testPath : testPaths)
+ {
+ {
+ directory_iterator it(testPath, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ directory_iterator it(testPath, opts, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath));
+ TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath, opts));
+ }
+ }
+}
+
+TEST_CASE(access_denied_test_case)
+{
+ using namespace fs;
+ scoped_test_env env;
+ path const testDir = env.make_env_path("dir1");
+ path const testFile = testDir / "testFile";
+ env.create_dir(testDir);
+ env.create_file(testFile, 42);
+
+ // Test that we can iterator over the directory before changing the perms
+ {
+ directory_iterator it(testDir);
+ TEST_REQUIRE(it != directory_iterator{});
+ }
+ // Change the permissions so we can no longer iterate
+ permissions(testDir, perms::none);
+
+ // Check that the construction fails when skip_permissions_denied is
+ // not given.
+ {
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == directory_iterator{});
+ }
+ // Check that construction does not report an error when
+ // 'skip_permissions_denied' is given.
+ {
+ std::error_code ec;
+ directory_iterator it(testDir, directory_options::skip_permission_denied, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it == directory_iterator{});
+ }
+}
+
+
+TEST_CASE(access_denied_to_file_test_case)
+{
+ using namespace fs;
+ scoped_test_env env;
+ path const testFile = env.make_env_path("file1");
+ env.create_file(testFile, 42);
+
+ // Change the permissions so we can no longer iterate
+ permissions(testFile, perms::none);
+
+ // Check that the construction fails when skip_permissions_denied is
+ // not given.
+ {
+ std::error_code ec;
+ directory_iterator it(testFile, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == directory_iterator{});
+ }
+ // Check that construction still fails when 'skip_permissions_denied' is given
+ // because we tried to open a file and not a directory.
+ {
+ std::error_code ec;
+ directory_iterator it(testFile, directory_options::skip_permission_denied, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == directory_iterator{});
+ }
+}
+
+TEST_CASE(test_open_on_empty_directory_equals_end)
+{
+ scoped_test_env env;
+ const path testDir = env.make_env_path("dir1");
+ env.create_dir(testDir);
+
+ const directory_iterator endIt;
+ {
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ directory_iterator it(testDir);
+ TEST_CHECK(it == endIt);
+ }
+}
+
+TEST_CASE(test_open_on_directory_succeeds)
+{
+ const path testDir = StaticEnv::Dir;
+ std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
+ std::end( StaticEnv::DirIterationList));
+ const directory_iterator endIt{};
+
+ {
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it != endIt);
+ TEST_CHECK(dir_contents.count(*it));
+ }
+ {
+ directory_iterator it(testDir);
+ TEST_CHECK(it != endIt);
+ TEST_CHECK(dir_contents.count(*it));
+ }
+}
+
+TEST_CASE(test_open_on_file_fails)
+{
+ const path testFile = StaticEnv::File;
+ const directory_iterator endIt{};
+ {
+ std::error_code ec;
+ directory_iterator it(testFile, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ TEST_CHECK_THROW(filesystem_error, directory_iterator(testFile));
+ }
+}
+
+TEST_CASE(test_open_on_empty_string)
+{
+ const path testPath = "";
+ const directory_iterator endIt{};
+
+ std::error_code ec;
+ directory_iterator it(testPath, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(test_open_on_dot_dir)
+{
+ const path testPath = ".";
+
+ std::error_code ec;
+ directory_iterator it(testPath, ec);
+ TEST_CHECK(!ec);
+}
+
+TEST_CASE(test_open_on_symlink)
+{
+ const path symlinkToDir = StaticEnv::SymlinkToDir;
+ std::set<path> dir_contents;
+ for (path const& p : StaticEnv::DirIterationList) {
+ dir_contents.insert(p.filename());
+ }
+ const directory_iterator endIt{};
+
+ {
+ std::error_code ec;
+ directory_iterator it(symlinkToDir, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it != endIt);
+ path const& entry = *it;
+ TEST_CHECK(dir_contents.count(entry.filename()));
+ }
+ {
+ std::error_code ec;
+ directory_iterator it(symlinkToDir,
+ directory_options::follow_directory_symlink, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it != endIt);
+ path const& entry = *it;
+ TEST_CHECK(dir_contents.count(entry.filename()));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator::directory_iterator() noexcept
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+int main() {
+ {
+ static_assert(std::is_nothrow_default_constructible<fs::directory_iterator>::value, "");
+ }
+ {
+ fs::directory_iterator d1;
+ const fs::directory_iterator d2;
+ assert(d1 == d2);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator& operator++();
+// directory_iterator& increment(error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+#include <iostream>
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_increment_tests)
+
+TEST_CASE(test_increment_signatures)
+{
+ using D = directory_iterator;
+ directory_iterator d; ((void)d);
+ std::error_code ec; ((void)ec);
+
+ ASSERT_SAME_TYPE(decltype(++d), directory_iterator&);
+ ASSERT_NOT_NOEXCEPT(++d);
+
+ ASSERT_SAME_TYPE(decltype(d.increment(ec)), directory_iterator&);
+ ASSERT_NOT_NOEXCEPT(d.increment(ec));
+}
+
+TEST_CASE(test_prefix_increment)
+{
+ const path testDir = StaticEnv::Dir;
+ const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
+ std::end( StaticEnv::DirIterationList));
+ const directory_iterator endIt{};
+
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ directory_iterator& it_ref = ++it;
+ TEST_CHECK(&it_ref == &it);
+ }
+
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(test_postfix_increment)
+{
+ const path testDir = StaticEnv::Dir;
+ const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
+ std::end( StaticEnv::DirIterationList));
+ const directory_iterator endIt{};
+
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ const path entry2 = *it++;
+ TEST_CHECK(entry2 == entry);
+ }
+
+ TEST_CHECK(it == endIt);
+}
+
+
+TEST_CASE(test_increment_method)
+{
+ const path testDir = StaticEnv::Dir;
+ const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
+ std::end( StaticEnv::DirIterationList));
+ const directory_iterator endIt{};
+
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ directory_iterator& it_ref = it.increment(ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(&it_ref == &it);
+ }
+
+ TEST_CHECK(it == endIt);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator(directory_iterator&&) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_move_construct_tests)
+
+TEST_CASE(test_constructor_signature)
+{
+ using D = directory_iterator;
+ static_assert(std::is_nothrow_move_constructible<D>::value, "");
+}
+
+TEST_CASE(test_move_end_iterator)
+{
+ const directory_iterator endIt;
+ directory_iterator endIt2{};
+
+ directory_iterator it(std::move(endIt2));
+ TEST_CHECK(it == endIt);
+ TEST_CHECK(endIt2 == endIt);
+}
+
+TEST_CASE(test_move_valid_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+ const directory_iterator endIt{};
+
+ directory_iterator it(testDir);
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+
+ const directory_iterator it2(std::move(it));
+ TEST_CHECK(*it2 == entry);
+
+ TEST_CHECK(it == it2 || it == endIt);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator& operator=(directory_iterator const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+// The filesystem specification explicitly allows for self-move on
+// the directory iterators. Turn off this warning so we can test it.
+#if defined(__clang__)
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_move_assign_tests)
+
+TEST_CASE(test_assignment_signature)
+{
+ using D = directory_iterator;
+ static_assert(std::is_nothrow_move_assignable<D>::value, "");
+}
+
+TEST_CASE(test_move_to_end_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+
+ directory_iterator from(testDir);
+ TEST_REQUIRE(from != directory_iterator{});
+ const path entry = *from;
+
+ directory_iterator to{};
+ to = std::move(from);
+ TEST_REQUIRE(to != directory_iterator{});
+ TEST_CHECK(*to == entry);
+}
+
+
+TEST_CASE(test_move_from_end_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+
+ directory_iterator from{};
+
+ directory_iterator to(testDir);
+ TEST_REQUIRE(to != from);
+
+ to = std::move(from);
+ TEST_REQUIRE(to == directory_iterator{});
+ TEST_REQUIRE(from == directory_iterator{});
+}
+
+TEST_CASE(test_move_valid_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+ const directory_iterator endIt{};
+
+ directory_iterator it(testDir);
+ TEST_REQUIRE(it != endIt);
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+
+ directory_iterator it2(testDir);
+ TEST_REQUIRE(it2 != it);
+ const path entry2 = *it2;
+ TEST_CHECK(entry2 != entry);
+
+ it2 = std::move(it);
+ TEST_REQUIRE(it2 != directory_iterator{});
+ TEST_CHECK(*it2 == entry);
+}
+
+TEST_CASE(test_returns_reference_to_self)
+{
+ directory_iterator it;
+ directory_iterator it2;
+ directory_iterator& ref = (it2 = it);
+ TEST_CHECK(&ref == &it2);
+}
+
+
+TEST_CASE(test_self_move)
+{
+ // Create two non-equal iterators that have exactly the same state.
+ directory_iterator it(StaticEnv::Dir);
+ directory_iterator it2(StaticEnv::Dir);
+ ++it; ++it2;
+ TEST_CHECK(it != it2);
+ TEST_CHECK(*it2 == *it);
+
+ it = std::move(it);
+ TEST_CHECK(*it2 == *it);
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// directory_iterator begin(directory_iterator iter) noexcept;
+// directory_iterator end(directory_iterator iter) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+#include <iostream>
+
+using namespace fs;
+
+TEST_SUITE(directory_iterator_begin_end_tests)
+
+TEST_CASE(test_function_signatures)
+{
+ using D = directory_iterator;
+ directory_iterator d; ((void)d);
+
+ ASSERT_SAME_TYPE(decltype(begin(d)), directory_iterator);
+ ASSERT_NOEXCEPT(begin(std::move(d)));
+
+ ASSERT_SAME_TYPE(decltype(end(d)), directory_iterator);
+ ASSERT_NOEXCEPT(end(std::move(d)));
+}
+
+TEST_CASE(test_ranged_for_loop)
+{
+ const path testDir = StaticEnv::Dir;
+ std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
+ std::end( StaticEnv::DirIterationList));
+
+ std::error_code ec;
+ directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ for (auto& elem : it) {
+ TEST_CHECK(dir_contents.erase(elem) == 1);
+ }
+ TEST_CHECK(dir_contents.empty());
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+// typedef ... value_type;
+// typedef ... difference_type;
+// typedef ... pointer;
+// typedef ... reference;
+// typedef ... iterator_category
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+int main() {
+ using namespace fs;
+ using D = directory_iterator;
+ ASSERT_SAME_TYPE(D::value_type, directory_entry);
+ ASSERT_SAME_TYPE(D::difference_type, std::ptrdiff_t);
+ ASSERT_SAME_TYPE(D::pointer, const directory_entry*);
+ ASSERT_SAME_TYPE(D::reference, const directory_entry&);
+ ASSERT_SAME_TYPE(D::iterator_category, std::input_iterator_tag);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class file_status
+
+// explicit file_status() noexcept;
+// explicit file_status(file_type, perms prms = perms::unknown) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_convertible.hpp"
+
+
+int main() {
+ using namespace fs;
+ // Default ctor
+ {
+ static_assert(std::is_nothrow_default_constructible<file_status>::value,
+ "The default constructor must be noexcept");
+ static_assert(test_convertible<file_status>(),
+ "The default constructor must not be explicit");
+ const file_status f;
+ assert(f.type() == file_type::none);
+ assert(f.permissions() == perms::unknown);
+ }
+
+ // Unary ctor
+ {
+ static_assert(std::is_nothrow_constructible<file_status, file_type>::value,
+ "This constructor must be noexcept");
+ static_assert(!test_convertible<file_status, file_type>(),
+ "This constructor must be explicit");
+
+ const file_status f(file_type::not_found);
+ assert(f.type() == file_type::not_found);
+ assert(f.permissions() == perms::unknown);
+ }
+ // Binary ctor
+ {
+ static_assert(std::is_nothrow_constructible<file_status, file_type, perms>::value,
+ "This constructor must be noexcept");
+ static_assert(!test_convertible<file_status, file_type, perms>(),
+ "This constructor must b explicit");
+ const file_status f(file_type::regular, perms::owner_read);
+ assert(f.type() == file_type::regular);
+ assert(f.permissions() == perms::owner_read);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class file_status
+
+// void type(file_type) noexcept;
+// void permissions(perms) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+
+int main() {
+ using namespace fs;
+
+ file_status st;
+
+ // type test
+ {
+ static_assert(noexcept(st.type(file_type::regular)),
+ "operation must be noexcept");
+ static_assert(std::is_same<decltype(st.type(file_type::regular)), void>::value,
+ "operation must return void");
+ assert(st.type() != file_type::regular);
+ st.type(file_type::regular);
+ assert(st.type() == file_type::regular);
+ }
+ // permissions test
+ {
+ static_assert(noexcept(st.permissions(perms::owner_read)),
+ "operation must be noexcept");
+ static_assert(std::is_same<decltype(st.permissions(perms::owner_read)), void>::value,
+ "operation must return void");
+ assert(st.permissions() != perms::owner_read);
+ st.permissions(perms::owner_read);
+ assert(st.permissions() == perms::owner_read);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class file_status
+
+// file_type type() const noexcept;
+// perms permissions(p) const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+
+int main() {
+ using namespace fs;
+
+ const file_status st(file_type::regular, perms::owner_read);
+
+ // type test
+ {
+ static_assert(noexcept(st.type()),
+ "operation must be noexcept");
+ static_assert(std::is_same<decltype(st.type()), file_type>::value,
+ "operation must return file_type");
+ assert(st.type() == file_type::regular);
+ }
+ // permissions test
+ {
+ static_assert(noexcept(st.permissions()),
+ "operation must be noexcept");
+ static_assert(std::is_same<decltype(st.permissions()), perms>::value,
+ "operation must return perms");
+ assert(st.permissions() == perms::owner_read);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class filesystem_error
+
+// filesystem_error(const string& what_arg, error_code ec);
+// filesystem_error(const string& what_arg, const path& p1, error_code ec);
+// filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec);
+// const std::error_code& code() const;
+// const char* what() const noexcept;
+// const path& path1() const noexcept;
+// const path& path2() const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+void test_constructors() {
+ using namespace fs;
+
+ // The string returned by "filesystem_error::what() must contain runtime_error::what()
+ const std::string what_arg = "Hello World";
+ const std::string what_contains = std::runtime_error(what_arg).what();
+ assert(what_contains.find(what_arg) != std::string::npos);
+ auto CheckWhat = [what_contains](filesystem_error const& e) {
+ std::string s = e.what();
+ assert(s.find(what_contains) != std::string::npos);
+ };
+
+ std::error_code ec = std::make_error_code(std::errc::file_exists);
+ const path p1("foo");
+ const path p2("bar");
+
+ // filesystem_error(const string& what_arg, error_code ec);
+ {
+ ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, ec));
+ filesystem_error e(what_arg, ec);
+ CheckWhat(e);
+ assert(e.code() == ec);
+ assert(e.path1().empty() && e.path2().empty());
+ }
+ // filesystem_error(const string& what_arg, const path&, error_code ec);
+ {
+ ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, ec));
+ filesystem_error e(what_arg, p1, ec);
+ CheckWhat(e);
+ assert(e.code() == ec);
+ assert(e.path1() == p1);
+ assert(e.path2().empty());
+ }
+ // filesystem_error(const string& what_arg, const path&, const path&, error_code ec);
+ {
+ ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, p2, ec));
+ filesystem_error e(what_arg, p1, p2, ec);
+ CheckWhat(e);
+ assert(e.code() == ec);
+ assert(e.path1() == p1);
+ assert(e.path2() == p2);
+ }
+}
+
+void test_signatures()
+{
+ using namespace fs;
+ const path p;
+ std::error_code ec;
+ const filesystem_error e("lala", ec);
+ // const path& path1() const noexcept;
+ {
+ ASSERT_SAME_TYPE(path const&, decltype(e.path1()));
+ ASSERT_NOEXCEPT(e.path1());
+ }
+ // const path& path2() const noexcept
+ {
+ ASSERT_SAME_TYPE(path const&, decltype(e.path2()));
+ ASSERT_NOEXCEPT(e.path2());
+ }
+ // const char* what() const noexcept
+ {
+ ASSERT_SAME_TYPE(const char*, decltype(e.what()));
+ ASSERT_NOEXCEPT(e.what());
+ }
+}
+
+int main() {
+ static_assert(std::is_base_of<std::system_error, fs::filesystem_error>::value, "");
+ test_constructors();
+ test_signatures();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class Source>
+// path(const Source& source);
+// template <class InputIterator>
+// path(InputIterator first, InputIterator last);
+
+
+#include "filesystem_include.hpp"
+#include <iterator>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.hpp"
+
+
+
+template <class It>
+std::reverse_iterator<It> mkRev(It it) {
+ return std::reverse_iterator<It>(it);
+}
+
+void checkIteratorConcepts() {
+ using namespace fs;
+ using It = path::iterator;
+ using Traits = std::iterator_traits<It>;
+ ASSERT_SAME_TYPE(Traits::iterator_category, std::bidirectional_iterator_tag);
+ ASSERT_SAME_TYPE(Traits::value_type, path);
+ ASSERT_SAME_TYPE(Traits::pointer, path const*);
+ ASSERT_SAME_TYPE(Traits::reference, path const&);
+ {
+ It it;
+ ASSERT_SAME_TYPE(It&, decltype(++it));
+ ASSERT_SAME_TYPE(It, decltype(it++));
+ ASSERT_SAME_TYPE(It&, decltype(--it));
+ ASSERT_SAME_TYPE(It, decltype(it--));
+ ASSERT_SAME_TYPE(Traits::reference, decltype(*it));
+ ASSERT_SAME_TYPE(Traits::pointer, decltype(it.operator->()));
+ ASSERT_SAME_TYPE(std::string const&, decltype(it->native()));
+ ASSERT_SAME_TYPE(bool, decltype(it == it));
+ ASSERT_SAME_TYPE(bool, decltype(it != it));
+ }
+ {
+ path const p;
+ ASSERT_SAME_TYPE(It, decltype(p.begin()));
+ ASSERT_SAME_TYPE(It, decltype(p.end()));
+ assert(p.begin() == p.end());
+ }
+}
+
+void checkBeginEndBasic() {
+ using namespace fs;
+ using It = path::iterator;
+ {
+ path const p;
+ ASSERT_SAME_TYPE(It, decltype(p.begin()));
+ ASSERT_SAME_TYPE(It, decltype(p.end()));
+ assert(p.begin() == p.end());
+ }
+ {
+ path const p("foo");
+ It default_constructed;
+ default_constructed = p.begin();
+ assert(default_constructed == p.begin());
+ assert(default_constructed != p.end());
+ default_constructed = p.end();
+ assert(default_constructed == p.end());
+ assert(default_constructed != p.begin());
+ }
+ {
+ path p("//root_name//first_dir////second_dir");
+ const path expect[] = {"/", "root_name", "first_dir", "second_dir"};
+ assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect)));
+ assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect)));
+
+ }
+ {
+ path p("////foo/bar/baz///");
+ const path expect[] = {"/", "foo", "bar", "baz", ""};
+ assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect)));
+ assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect)));
+
+ }
+
+}
+
+int main() {
+ using namespace fs;
+ checkIteratorConcepts();
+ checkBeginEndBasic(); // See path.decompose.pass.cpp for more tests.
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& operator/=(path const&)
+// template <class Source>
+// path& operator/=(Source const&);
+// template <class Source>
+// path& append(Source const&);
+// template <class InputIterator>
+// path& append(InputIterator first, InputIterator last);
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <string_view>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+#include "verbose_assert.h"
+
+
+struct AppendOperatorTestcase {
+ MultiStringType lhs;
+ MultiStringType rhs;
+ MultiStringType expect;
+};
+
+#define S(Str) MKSTR(Str)
+const AppendOperatorTestcase Cases[] =
+ {
+ {S(""), S(""), S("")}
+ , {S("p1"), S("p2"), S("p1/p2")}
+ , {S("p1/"), S("p2"), S("p1/p2")}
+ , {S("p1"), S("/p2"), S("/p2")}
+ , {S("p1/"), S("/p2"), S("/p2")}
+ , {S("p1"), S("\\p2"), S("p1/\\p2")}
+ , {S("p1\\"), S("p2"), S("p1\\/p2")}
+ , {S("p1\\"), S("\\p2"), S("p1\\/\\p2")}
+ , {S(""), S("p2"), S("p2")}
+ , {S("/p1"), S("p2"), S("/p1/p2")}
+ , {S("/p1"), S("/p2"), S("/p2")}
+ , {S("/p1/p3"), S("p2"), S("/p1/p3/p2")}
+ , {S("/p1/p3/"), S("p2"), S("/p1/p3/p2")}
+ , {S("/p1/"), S("p2"), S("/p1/p2")}
+ , {S("/p1/p3/"), S("/p2/p4"), S("/p2/p4")}
+ , {S("/"), S(""), S("/")}
+ , {S("/p1"), S("/p2/"), S("/p2/")}
+ , {S("p1"), S(""), S("p1/")}
+ , {S("p1/"), S(""), S("p1/")}
+ };
+
+
+const AppendOperatorTestcase LongLHSCases[] =
+ {
+ {S("p1"), S("p2"), S("p1/p2")}
+ , {S("p1/"), S("p2"), S("p1/p2")}
+ , {S("p1"), S("/p2"), S("/p2")}
+ , {S("/p1"), S("p2"), S("/p1/p2")}
+ };
+#undef S
+
+
+// The append operator may need to allocate a temporary buffer before a code_cvt
+// conversion. Test if this allocation occurs by:
+// 1. Create a path, `LHS`, and reserve enough space to append `RHS`.
+// This prevents `LHS` from allocating during the actual appending.
+// 2. Create a `Source` object `RHS`, which represents a "large" string.
+// (The string must not trigger the SSO)
+// 3. Append `RHS` to `LHS` and check for the expected allocation behavior.
+template <class CharT>
+void doAppendSourceAllocTest(AppendOperatorTestcase const& TC)
+{
+ using namespace fs;
+ using Ptr = CharT const*;
+ using Str = std::basic_string<CharT>;
+ using StrView = std::basic_string_view<CharT>;
+ using InputIter = input_iterator<Ptr>;
+
+ const Ptr L = TC.lhs;
+ Str RShort = (Ptr)TC.rhs;
+ Str EShort = (Ptr)TC.expect;
+ assert(RShort.size() >= 2);
+ CharT c = RShort.back();
+ RShort.append(100, c);
+ EShort.append(100, c);
+ const Ptr R = RShort.data();
+ const Str& E = EShort;
+ std::size_t ReserveSize = E.size() + 3;
+ // basic_string
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ Str RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS /= RHS;
+ }
+ ASSERT_PRED(PathEq, LHS , E);
+ }
+ // basic_string_view
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ StrView RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS /= RHS;
+ }
+ assert(PathEq(LHS, E));
+ }
+ // CharT*
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ Ptr RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS /= RHS;
+ }
+ assert(PathEq(LHS, E));
+ }
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ Ptr RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS.append(RHS, StrEnd(RHS));
+ }
+ assert(PathEq(LHS, E));
+ }
+ // input iterator - For non-native char types, appends needs to copy the
+ // iterator range into a contiguous block of memory before it can perform the
+ // code_cvt conversions.
+ // For "char" no allocations will be performed because no conversion is
+ // required.
+ bool DisableAllocations = std::is_same<CharT, char>::value;
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ InputIter RHS(R);
+ {
+ RequireAllocationGuard g; // requires 1 or more allocations occur by default
+ if (DisableAllocations) g.requireExactly(0);
+ LHS /= RHS;
+ }
+ assert(PathEq(LHS, E));
+ }
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ InputIter RHS(R);
+ InputIter REnd(StrEnd(R));
+ {
+ RequireAllocationGuard g;
+ if (DisableAllocations) g.requireExactly(0);
+ LHS.append(RHS, REnd);
+ }
+ assert(PathEq(LHS, E));
+ }
+}
+
+template <class CharT>
+void doAppendSourceTest(AppendOperatorTestcase const& TC)
+{
+ using namespace fs;
+ using Ptr = CharT const*;
+ using Str = std::basic_string<CharT>;
+ using StrView = std::basic_string_view<CharT>;
+ using InputIter = input_iterator<Ptr>;
+ const Ptr L = TC.lhs;
+ const Ptr R = TC.rhs;
+ const Ptr E = TC.expect;
+ // basic_string
+ {
+ path Result(L);
+ Str RHS(R);
+ path& Ref = (Result /= RHS);
+ ASSERT_EQ(Result, E)
+ << DISPLAY(L) << DISPLAY(R);
+ assert(&Ref == &Result);
+ }
+ {
+ path LHS(L);
+ Str RHS(R);
+ path& Ref = LHS.append(RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ // basic_string_view
+ {
+ path LHS(L);
+ StrView RHS(R);
+ path& Ref = (LHS /= RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ StrView RHS(R);
+ path& Ref = LHS.append(RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ // Char*
+ {
+ path LHS(L);
+ Str RHS(R);
+ path& Ref = (LHS /= RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ Ptr RHS(R);
+ path& Ref = LHS.append(RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ Ptr RHS(R);
+ path& Ref = LHS.append(RHS, StrEnd(RHS));
+ ASSERT_PRED(PathEq, LHS, E)
+ << DISPLAY(L) << DISPLAY(R);
+ assert(&Ref == &LHS);
+ }
+ // iterators
+ {
+ path LHS(L);
+ InputIter RHS(R);
+ path& Ref = (LHS /= RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L); InputIter RHS(R);
+ path& Ref = LHS.append(RHS);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ InputIter RHS(R);
+ InputIter REnd(StrEnd(R));
+ path& Ref = LHS.append(RHS, REnd);
+ assert(PathEq(LHS, E));
+ assert(&Ref == &LHS);
+ }
+}
+
+
+
+template <class It, class = decltype(fs::path{}.append(std::declval<It>()))>
+constexpr bool has_append(int) { return true; }
+template <class It>
+constexpr bool has_append(long) { return false; }
+
+template <class It, class = decltype(fs::path{}.operator/=(std::declval<It>()))>
+constexpr bool has_append_op(int) { return true; }
+template <class It>
+constexpr bool has_append_op(long) { return false; }
+
+template <class It>
+constexpr bool has_append() {
+ static_assert(has_append<It>(0) == has_append_op<It>(0), "must be same");
+ return has_append<It>(0) && has_append_op<It>(0);
+}
+
+void test_sfinae()
+{
+ using namespace fs;
+ {
+ using It = const char* const;
+ static_assert(has_append<It>(), "");
+ }
+ {
+ using It = input_iterator<const char*>;
+ static_assert(has_append<It>(), "");
+ }
+ {
+ struct Traits {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = const char;
+ using pointer = const char*;
+ using reference = const char&;
+ using difference_type = std::ptrdiff_t;
+ };
+ using It = input_iterator<const char*, Traits>;
+ static_assert(has_append<It>(), "");
+ }
+ {
+ using It = output_iterator<const char*>;
+ static_assert(!has_append<It>(), "");
+
+ }
+ {
+ static_assert(!has_append<int*>(), "");
+ }
+ {
+ static_assert(!has_append<char>(), "");
+ static_assert(!has_append<const char>(), "");
+ }
+}
+
+int main()
+{
+ using namespace fs;
+ for (auto const & TC : Cases) {
+ {
+ const char* LHS_In = TC.lhs;
+ const char* RHS_In = TC.rhs;
+ path LHS(LHS_In);
+ path RHS(RHS_In);
+ path& Res = (LHS /= RHS);
+ ASSERT_PRED(PathEq, Res, (const char*)TC.expect)
+ << DISPLAY(LHS_In) << DISPLAY(RHS_In);
+ assert(&Res == &LHS);
+ }
+ doAppendSourceTest<char> (TC);
+ doAppendSourceTest<wchar_t> (TC);
+ doAppendSourceTest<char16_t>(TC);
+ doAppendSourceTest<char32_t>(TC);
+ }
+ for (auto const & TC : LongLHSCases) {
+ doAppendSourceAllocTest<char>(TC);
+ doAppendSourceAllocTest<wchar_t>(TC);
+ }
+ test_sfinae();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& operator=(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+
+
+int main() {
+ using namespace fs;
+ path p("abc");
+ p = {};
+ assert(p.native() == "");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& operator=(path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+int main() {
+ using namespace fs;
+ static_assert(std::is_copy_assignable<path>::value, "");
+ static_assert(!std::is_nothrow_copy_assignable<path>::value, "should not be noexcept");
+ const std::string s("foo");
+ const path p(s);
+ path p2;
+ path& pref = (p2 = p);
+ assert(p.native() == s);
+ assert(p2.native() == s);
+ assert(&pref == &p2);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& operator=(path&&) noexcept
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+
+
+int main() {
+ using namespace fs;
+ static_assert(std::is_nothrow_move_assignable<path>::value, "");
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ const std::string s("we really really really really really really really "
+ "really really long string so that we allocate");
+ assert(globalMemCounter.checkOutstandingNewEq(1));
+ path p(s);
+ {
+ DisableAllocationGuard g;
+ path p2;
+ path& pref = (p2 = std::move(p));
+ assert(p2.native() == s);
+ assert(p.native() != s); // Testing moved from state
+ assert(&pref == &p2);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class Source>
+// path& operator=(Source const&);
+// path& operator=(string_type&&);
+// template <class Source>
+// path& assign(Source const&);
+// template <class InputIterator>
+// path& assign(InputIterator first, InputIterator last);
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <string_view>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+#include <iostream>
+
+
+template <class CharT>
+void RunTestCase(MultiStringType const& MS) {
+ using namespace fs;
+ const char* Expect = MS;
+ const CharT* TestPath = MS;
+ const CharT* TestPathEnd = StrEnd(TestPath);
+ const std::size_t Size = TestPathEnd - TestPath;
+ const std::size_t SSize = StrEnd(Expect) - Expect;
+ assert(Size == SSize);
+ //////////////////////////////////////////////////////////////////////////////
+ // basic_string<Char, Traits, Alloc>
+ {
+ const std::basic_string<CharT> S(TestPath);
+ path p; PathReserve(p, S.length() + 1);
+ {
+ // string provides a contiguous iterator. No allocation needed.
+ DisableAllocationGuard g;
+ path& pref = (p = S);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ assert(p.string<CharT>() == S);
+ }
+ {
+ const std::basic_string<CharT> S(TestPath);
+ path p; PathReserve(p, S.length() + 1);
+ {
+ DisableAllocationGuard g;
+ path& pref = p.assign(S);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ assert(p.string<CharT>() == S);
+ }
+ // basic_string<Char, Traits, Alloc>
+ {
+ const std::basic_string_view<CharT> S(TestPath);
+ path p; PathReserve(p, S.length() + 1);
+ {
+ // string provides a contiguous iterator. No allocation needed.
+ DisableAllocationGuard g;
+ path& pref = (p = S);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ assert(p.string<CharT>() == S);
+ }
+ {
+ const std::basic_string_view<CharT> S(TestPath);
+ path p; PathReserve(p, S.length() + 1);
+ {
+ DisableAllocationGuard g;
+ path& pref = p.assign(S);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ assert(p.string<CharT>() == S);
+ }
+ //////////////////////////////////////////////////////////////////////////////
+ // Char* pointers
+ {
+ path p; PathReserve(p, Size + 1);
+ {
+ // char* pointers are contiguous and can be used with code_cvt directly.
+ // no allocations needed.
+ DisableAllocationGuard g;
+ path& pref = (p = TestPath);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ {
+ path p; PathReserve(p, Size + 1);
+ {
+ DisableAllocationGuard g;
+ path& pref = p.assign(TestPath);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ {
+ path p; PathReserve(p, Size + 1);
+ {
+ DisableAllocationGuard g;
+ path& pref = p.assign(TestPath, TestPathEnd);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ //////////////////////////////////////////////////////////////////////////////
+ // Iterators
+ {
+ using It = input_iterator<const CharT*>;
+ path p; PathReserve(p, Size + 1);
+ It it(TestPath);
+ {
+ // Iterators cannot be used with code_cvt directly. This assignment
+ // may allocate if it's larger than a "short-string".
+ path& pref = (p = it);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ {
+ using It = input_iterator<const CharT*>;
+ path p; PathReserve(p, Size + 1);
+ It it(TestPath);
+ {
+ path& pref = p.assign(it);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ {
+ using It = input_iterator<const CharT*>;
+ path p; PathReserve(p, Size + 1);
+ It it(TestPath);
+ It e(TestPathEnd);
+ {
+ path& pref = p.assign(it, e);
+ assert(&pref == &p);
+ }
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+}
+
+template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>
+constexpr bool has_assign(int) { return true; }
+template <class It>
+constexpr bool has_assign(long) { return false; }
+template <class It>
+constexpr bool has_assign() { return has_assign<It>(0); }
+
+void test_sfinae() {
+ using namespace fs;
+ {
+ using It = const char* const;
+ static_assert(std::is_assignable<path, It>::value, "");
+ static_assert(has_assign<It>(), "");
+ }
+ {
+ using It = input_iterator<const char*>;
+ static_assert(std::is_assignable<path, It>::value, "");
+ static_assert(has_assign<It>(), "");
+ }
+ {
+ struct Traits {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = const char;
+ using pointer = const char*;
+ using reference = const char&;
+ using difference_type = std::ptrdiff_t;
+ };
+ using It = input_iterator<const char*, Traits>;
+ static_assert(std::is_assignable<path, It>::value, "");
+ static_assert(has_assign<It>(), "");
+ }
+ {
+ using It = output_iterator<const char*>;
+ static_assert(!std::is_assignable<path, It>::value, "");
+ static_assert(!has_assign<It>(), "");
+
+ }
+ {
+ static_assert(!std::is_assignable<path, int*>::value, "");
+ static_assert(!has_assign<int*>(), "");
+ }
+}
+
+void RunStringMoveTest(const char* Expect) {
+ using namespace fs;
+ std::string ss(Expect);
+ path p;
+ {
+ DisableAllocationGuard g; ((void)g);
+ path& pr = (p = std::move(ss));
+ assert(&pr == &p);
+ }
+ assert(p == Expect);
+ {
+ // Signature test
+ ASSERT_NOEXCEPT(p = std::move(ss));
+ }
+}
+
+int main() {
+ for (auto const& MS : PathList) {
+ RunTestCase<char>(MS);
+ RunTestCase<wchar_t>(MS);
+ RunTestCase<char16_t>(MS);
+ RunTestCase<char32_t>(MS);
+ RunStringMoveTest(MS);
+ }
+ test_sfinae();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// int compare(path const&) const noexcept;
+// int compare(string_type const&) const;
+// int compare(value_type const*) const;
+//
+// bool operator==(path const&, path const&) noexcept;
+// bool operator!=(path const&, path const&) noexcept;
+// bool operator< (path const&, path const&) noexcept;
+// bool operator<=(path const&, path const&) noexcept;
+// bool operator> (path const&, path const&) noexcept;
+// bool operator>=(path const&, path const&) noexcept;
+//
+// size_t hash_value(path const&) noexcept;
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+#include "verbose_assert.h"
+
+struct PathCompareTest {
+ const char* LHS;
+ const char* RHS;
+ int expect;
+};
+
+#define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+#define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+#define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
+#define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
+const PathCompareTest CompareTestCases[] =
+{
+ {"", "", 0},
+ {"a", "", 1},
+ {"", "a", -1},
+ {"a/b/c", "a/b/c", 0},
+ {"b/a/c", "a/b/c", 1},
+ {"a/b/c", "b/a/c", -1},
+ {"a/b", "a/b/c", -1},
+ {"a/b/c", "a/b", 1},
+ {"a/b/", "a/b/.", -1},
+ {"a/b/", "a/b", 1},
+ {"a/b//////", "a/b/////.", -1},
+ {"a/.././b", "a///..//.////b", 0},
+ {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators
+ {"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory
+ {"/foo/bar/", "/foo/bar", 1}, // trailing separator
+ {"//" LONGA "////" LONGB "/" LONGC "///" LONGD, "//" LONGA "/" LONGB "/" LONGC "/" LONGD, 0},
+ { LONGA "/" LONGB "/" LONGC, LONGA "/" LONGB "/" LONGB, 1}
+
+};
+#undef LONGA
+#undef LONGB
+#undef LONGC
+#undef LONGD
+
+static inline int normalize_ret(int ret)
+{
+ return ret < 0 ? -1 : (ret > 0 ? 1 : 0);
+}
+
+int main()
+{
+ using namespace fs;
+ for (auto const & TC : CompareTestCases) {
+ const path p1(TC.LHS);
+ const path p2(TC.RHS);
+ const std::string R(TC.RHS);
+ const std::string_view RV(TC.RHS);
+ const int E = TC.expect;
+ { // compare(...) functions
+ DisableAllocationGuard g; // none of these operations should allocate
+
+ // check runtime results
+ int ret1 = normalize_ret(p1.compare(p2));
+ int ret2 = normalize_ret(p1.compare(R));
+ int ret3 = normalize_ret(p1.compare(TC.RHS));
+ int ret4 = normalize_ret(p1.compare(RV));
+
+ g.release();
+ ASSERT_EQ(ret1, ret2);
+ ASSERT_EQ(ret1, ret3);
+ ASSERT_EQ(ret1, ret4);
+ ASSERT_EQ(ret1, E)
+ << DISPLAY(TC.LHS) << DISPLAY(TC.RHS);
+
+ // check signatures
+ ASSERT_NOEXCEPT(p1.compare(p2));
+ }
+ { // comparison operators
+ DisableAllocationGuard g; // none of these operations should allocate
+
+ // Check runtime result
+ assert((p1 == p2) == (E == 0));
+ assert((p1 != p2) == (E != 0));
+ assert((p1 < p2) == (E < 0));
+ assert((p1 <= p2) == (E <= 0));
+ assert((p1 > p2) == (E > 0));
+ assert((p1 >= p2) == (E >= 0));
+
+ // Check signatures
+ ASSERT_NOEXCEPT(p1 == p2);
+ ASSERT_NOEXCEPT(p1 != p2);
+ ASSERT_NOEXCEPT(p1 < p2);
+ ASSERT_NOEXCEPT(p1 <= p2);
+ ASSERT_NOEXCEPT(p1 > p2);
+ ASSERT_NOEXCEPT(p1 >= p2);
+ }
+ { // check hash values
+ auto h1 = hash_value(p1);
+ auto h2 = hash_value(p2);
+ assert((h1 == h2) == (p1 == p2));
+ // check signature
+ ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1)));
+ ASSERT_NOEXCEPT(hash_value(p1));
+ }
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& operator+=(const path& x);
+// path& operator+=(const string_type& x);
+// path& operator+=(string_view x);
+// path& operator+=(const value_type* x);
+// path& operator+=(value_type x);
+// template <class Source>
+// path& operator+=(const Source& x);
+// template <class EcharT>
+// path& operator+=(EcharT x);
+// template <class Source>
+// path& concat(const Source& x);
+// template <class InputIterator>
+// path& concat(InputIterator first, InputIterator last);
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <string>
+#include <string_view>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+struct ConcatOperatorTestcase {
+ MultiStringType lhs;
+ MultiStringType rhs;
+ MultiStringType expect;
+};
+
+#define LONGSTR "LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR"
+#define S(Str) MKSTR(Str)
+const ConcatOperatorTestcase Cases[] =
+ {
+ {S(""), S(""), S("")}
+ , {S("p1"), S("p2"), S("p1p2")}
+ , {S("p1/"), S("/p2"), S("p1//p2")}
+ , {S(""), S("\\foo/bar/baz"), S("\\foo/bar/baz")}
+ , {S("c:\\foo"), S(""), S("c:\\foo")}
+ , {S(LONGSTR), S("foo"), S(LONGSTR "foo")}
+ , {S("abcdefghijklmnopqrstuvwxyz/\\"), S("/\\123456789"), S("abcdefghijklmnopqrstuvwxyz/\\/\\123456789")}
+ };
+const ConcatOperatorTestcase LongLHSCases[] =
+ {
+ {S(""), S(LONGSTR), S(LONGSTR)}
+ , {S("p1/"), S(LONGSTR), S("p1/" LONGSTR)}
+ };
+const ConcatOperatorTestcase CharTestCases[] =
+ {
+ {S(""), S("P"), S("P")}
+ , {S("/fooba"), S("r"), S("/foobar")}
+ };
+#undef S
+#undef LONGSTR
+
+// The concat operator may need to allocate a temporary buffer before a code_cvt
+// conversion. Test if this allocation occurs by:
+// 1. Create a path, `LHS`, and reserve enough space to append `RHS`.
+// This prevents `LHS` from allocating during the actual appending.
+// 2. Create a `Source` object `RHS`, which represents a "large" string.
+// (The string must not trigger the SSO)
+// 3. Concat `RHS` to `LHS` and check for the expected allocation behavior.
+template <class CharT>
+void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC)
+{
+ using namespace fs;
+ using Ptr = CharT const*;
+ using Str = std::basic_string<CharT>;
+ using StrView = std::basic_string_view<CharT>;
+ using InputIter = input_iterator<Ptr>;
+
+ const Ptr L = TC.lhs;
+ const Ptr R = TC.rhs;
+ const Ptr E = TC.expect;
+ std::size_t ReserveSize = StrLen(E) + 1;
+ // basic_string
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ Str RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS += RHS;
+ }
+ assert(LHS == E);
+ }
+ // basic_string_view
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ StrView RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS += RHS;
+ }
+ assert(LHS == E);
+ }
+ // CharT*
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ Ptr RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS += RHS;
+ }
+ assert(LHS == E);
+ }
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ Ptr RHS(R);
+ {
+ DisableAllocationGuard g;
+ LHS.concat(RHS, StrEnd(RHS));
+ }
+ assert(LHS == E);
+ }
+ // input iterator - For non-native char types, appends needs to copy the
+ // iterator range into a contiguous block of memory before it can perform the
+ // code_cvt conversions.
+ // For "char" no allocations will be performed because no conversion is
+ // required.
+ bool DisableAllocations = std::is_same<CharT, char>::value;
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ InputIter RHS(R);
+ {
+ RequireAllocationGuard g; // requires 1 or more allocations occur by default
+ if (DisableAllocations) g.requireExactly(0);
+ LHS += RHS;
+ }
+ assert(LHS == E);
+ }
+ {
+ path LHS(L); PathReserve(LHS, ReserveSize);
+ InputIter RHS(R);
+ InputIter REnd(StrEnd(R));
+ {
+ RequireAllocationGuard g;
+ if (DisableAllocations) g.requireExactly(0);
+ LHS.concat(RHS, REnd);
+ }
+ assert(LHS == E);
+ }
+}
+
+template <class CharT>
+void doConcatSourceTest(ConcatOperatorTestcase const& TC)
+{
+ using namespace fs;
+ using Ptr = CharT const*;
+ using Str = std::basic_string<CharT>;
+ using StrView = std::basic_string_view<CharT>;
+ using InputIter = input_iterator<Ptr>;
+ const Ptr L = TC.lhs;
+ const Ptr R = TC.rhs;
+ const Ptr E = TC.expect;
+ // basic_string
+ {
+ path LHS(L);
+ Str RHS(R);
+ path& Ref = (LHS += RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ Str RHS(R);
+ path& Ref = LHS.concat(RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ // basic_string_view
+ {
+ path LHS(L);
+ StrView RHS(R);
+ path& Ref = (LHS += RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ StrView RHS(R);
+ path& Ref = LHS.concat(RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ // Char*
+ {
+ path LHS(L);
+ Str RHS(R);
+ path& Ref = (LHS += RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ Ptr RHS(R);
+ path& Ref = LHS.concat(RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ Ptr RHS(R);
+ path& Ref = LHS.concat(RHS, StrEnd(RHS));
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ // iterators
+ {
+ path LHS(L);
+ InputIter RHS(R);
+ path& Ref = (LHS += RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L); InputIter RHS(R);
+ path& Ref = LHS.concat(RHS);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS(L);
+ InputIter RHS(R);
+ InputIter REnd(StrEnd(R));
+ path& Ref = LHS.concat(RHS, REnd);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+}
+
+template <class CharT>
+void doConcatECharTest(ConcatOperatorTestcase const& TC)
+{
+ using namespace fs;
+ using Ptr = CharT const*;
+ const Ptr RStr = TC.rhs;
+ assert(StrLen(RStr) == 1);
+ const Ptr L = TC.lhs;
+ const CharT R = RStr[0];
+ const Ptr E = TC.expect;
+ {
+ path LHS(L);
+ path& Ref = (LHS += R);
+ assert(LHS == E);
+ assert(&Ref == &LHS);
+ }
+}
+
+
+template <class It, class = decltype(fs::path{}.concat(std::declval<It>()))>
+constexpr bool has_concat(int) { return true; }
+template <class It>
+constexpr bool has_concat(long) { return false; }
+
+template <class It, class = decltype(fs::path{}.operator+=(std::declval<It>()))>
+constexpr bool has_concat_op(int) { return true; }
+template <class It>
+constexpr bool has_concat_op(long) { return false; }
+template <class It>
+constexpr bool has_concat_op() { return has_concat_op<It>(0); }
+
+template <class It>
+constexpr bool has_concat() {
+ static_assert(has_concat<It>(0) == has_concat_op<It>(0), "must be same");
+ return has_concat<It>(0) && has_concat_op<It>(0);
+}
+
+void test_sfinae() {
+ using namespace fs;
+ {
+ static_assert(has_concat_op<char>(), "");
+ static_assert(has_concat_op<const char>(), "");
+ static_assert(has_concat_op<char16_t>(), "");
+ static_assert(has_concat_op<const char16_t>(), "");
+ }
+ {
+ using It = const char* const;
+ static_assert(has_concat<It>(), "");
+ }
+ {
+ using It = input_iterator<const char*>;
+ static_assert(has_concat<It>(), "");
+ }
+ {
+ struct Traits {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = const char;
+ using pointer = const char*;
+ using reference = const char&;
+ using difference_type = std::ptrdiff_t;
+ };
+ using It = input_iterator<const char*, Traits>;
+ static_assert(has_concat<It>(), "");
+ }
+ {
+ using It = output_iterator<const char*>;
+ static_assert(!has_concat<It>(), "");
+ }
+ {
+ static_assert(!has_concat<int>(0), "");
+ // operator+=(int) is well formed since it converts to operator+=(value_type)
+ // but concat(int) isn't valid because there is no concat(value_type).
+ // This should probably be addressed by a LWG issue.
+ static_assert(has_concat_op<int>(), "");
+ }
+ {
+ static_assert(!has_concat<int*>(), "");
+ }
+}
+
+int main()
+{
+ using namespace fs;
+ for (auto const & TC : Cases) {
+ {
+ path LHS((const char*)TC.lhs);
+ path RHS((const char*)TC.rhs);
+ path& Ref = (LHS += RHS);
+ assert(LHS == (const char*)TC.expect);
+ assert(&Ref == &LHS);
+ }
+ {
+ path LHS((const char*)TC.lhs);
+ std::string_view RHS((const char*)TC.rhs);
+ path& Ref = (LHS += RHS);
+ assert(LHS == (const char*)TC.expect);
+ assert(&Ref == &LHS);
+ }
+ doConcatSourceTest<char> (TC);
+ doConcatSourceTest<wchar_t> (TC);
+ doConcatSourceTest<char16_t>(TC);
+ doConcatSourceTest<char32_t>(TC);
+ }
+ for (auto const & TC : LongLHSCases) {
+ // Do path test
+ {
+ path LHS((const char*)TC.lhs);
+ path RHS((const char*)TC.rhs);
+ const char* E = TC.expect;
+ PathReserve(LHS, StrLen(E) + 5);
+ {
+ DisableAllocationGuard g;
+ path& Ref = (LHS += RHS);
+ assert(&Ref == &LHS);
+ }
+ assert(LHS == E);
+ }
+ {
+ path LHS((const char*)TC.lhs);
+ std::string_view RHS((const char*)TC.rhs);
+ const char* E = TC.expect;
+ PathReserve(LHS, StrLen(E) + 5);
+ {
+ DisableAllocationGuard g;
+ path& Ref = (LHS += RHS);
+ assert(&Ref == &LHS);
+ }
+ assert(LHS == E);
+ }
+ doConcatSourceAllocTest<char>(TC);
+ doConcatSourceAllocTest<wchar_t>(TC);
+ }
+ for (auto const& TC : CharTestCases) {
+ doConcatECharTest<char>(TC);
+ doConcatECharTest<wchar_t>(TC);
+ doConcatECharTest<char16_t>(TC);
+ doConcatECharTest<char32_t>(TC);
+ }
+ test_sfinae();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path(path const&)
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+int main() {
+ using namespace fs;
+ static_assert(std::is_copy_constructible<path>::value, "");
+ static_assert(!std::is_nothrow_copy_constructible<path>::value, "should not be noexcept");
+ const std::string s("foo");
+ const path p(s);
+ path p2(p);
+ assert(p.native() == s);
+ assert(p2.native() == s);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path() noexcept
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+int main() {
+ using namespace fs;
+ static_assert(std::is_nothrow_default_constructible<path>::value, "");
+ const path p;
+ assert(p.empty());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path(path&&) noexcept
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+
+
+int main() {
+ using namespace fs;
+ static_assert(std::is_nothrow_move_constructible<path>::value, "");
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ const std::string s("we really really really really really really really "
+ "really really long string so that we allocate");
+ assert(globalMemCounter.checkOutstandingNewEq(1));
+ path p(s);
+ {
+ DisableAllocationGuard g;
+ path p2(std::move(p));
+ assert(p2.native() == s);
+ assert(p.native() != s); // Testing moved from state
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class Source>
+// path(const Source& source);
+// template <class InputIterator>
+// path(InputIterator first, InputIterator last);
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "min_allocator.h"
+#include "filesystem_test_helper.hpp"
+
+
+template <class CharT, class ...Args>
+void RunTestCaseImpl(MultiStringType const& MS, Args... args) {
+ using namespace fs;
+ const char* Expect = MS;
+ const CharT* TestPath = MS;
+ const CharT* TestPathEnd = StrEnd(TestPath);
+ const std::size_t Size = TestPathEnd - TestPath;
+ const std::size_t SSize = StrEnd(Expect) - Expect;
+ assert(Size == SSize);
+ // StringTypes
+ {
+ const std::basic_string<CharT> S(TestPath);
+ path p(S, args...);
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ assert(p.string<CharT>() == S);
+ }
+ {
+ const std::basic_string_view<CharT> S(TestPath);
+ path p(S, args...);
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ assert(p.string<CharT>() == S);
+ }
+ // Char* pointers
+ {
+ path p(TestPath, args...);
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ {
+ path p(TestPath, TestPathEnd, args...);
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ // Iterators
+ {
+ using It = input_iterator<const CharT*>;
+ path p(It{TestPath}, args...);
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+ {
+ using It = input_iterator<const CharT*>;
+ path p(It{TestPath}, It{TestPathEnd}, args...);
+ assert(p.native() == Expect);
+ assert(p.string<CharT>() == TestPath);
+ }
+}
+
+template <class CharT, class ...Args>
+void RunTestCase(MultiStringType const& MS) {
+ RunTestCaseImpl<CharT>(MS);
+ RunTestCaseImpl<CharT>(MS, fs::path::format::auto_format);
+ RunTestCaseImpl<CharT>(MS, fs::path::format::native_format);
+ RunTestCaseImpl<CharT>(MS, fs::path::format::generic_format);
+}
+
+void test_sfinae() {
+ using namespace fs;
+ {
+ using It = const char* const;
+ static_assert(std::is_constructible<path, It>::value, "");
+ }
+ {
+ using It = input_iterator<const char*>;
+ static_assert(std::is_constructible<path, It>::value, "");
+ }
+ {
+ struct Traits {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = const char;
+ using pointer = const char*;
+ using reference = const char&;
+ using difference_type = std::ptrdiff_t;
+ };
+ using It = input_iterator<const char*, Traits>;
+ static_assert(std::is_constructible<path, It>::value, "");
+ }
+ {
+ using It = output_iterator<const char*>;
+ static_assert(!std::is_constructible<path, It>::value, "");
+
+ }
+ {
+ static_assert(!std::is_constructible<path, int*>::value, "");
+ }
+}
+
+int main() {
+ for (auto const& MS : PathList) {
+ RunTestCase<char>(MS);
+ RunTestCase<wchar_t>(MS);
+ RunTestCase<char16_t>(MS);
+ RunTestCase<char32_t>(MS);
+ }
+ test_sfinae();
+}
--- /dev/null
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <filesystem>
+
+// class path
+
+// bool empty() const noexcept;
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+// UNSUPPORTED: clang-3.3, clang-3.4, clang-3.5, clang-3.6, clang-3.7, clang-3.8
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+
+int main ()
+{
+ fs::path c;
+ c.empty(); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}}
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// 8.4.9 path decomposition [path.decompose]
+//------------------------------------------
+// path root_name() const;
+// path root_directory() const;
+// path root_path() const;
+// path relative_path() const;
+// path parent_path() const;
+// path filename() const;
+// path stem() const;
+// path extension() const;
+//-------------------------------
+// 8.4.10 path query [path.query]
+//-------------------------------
+// bool empty() const noexcept;
+// bool has_root_path() const;
+// bool has_root_name() const;
+// bool has_root_directory() const;
+// bool has_relative_path() const;
+// bool has_parent_path() const;
+// bool has_filename() const;
+// bool has_stem() const;
+// bool has_extension() const;
+// bool is_absolute() const;
+// bool is_relative() const;
+//-------------------------------
+// 8.5 path iterators [path.itr]
+//-------------------------------
+// iterator begin() const;
+// iterator end() const;
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+#include "assert_checkpoint.h"
+#include "verbose_assert.h"
+
+struct ComparePathExact {
+ bool operator()(std::string const& LHS, std::string const& RHS) const {
+ return LHS == RHS;
+ }
+};
+
+struct PathDecomposeTestcase
+{
+ std::string raw;
+ std::vector<std::string> elements;
+ std::string root_path;
+ std::string root_name;
+ std::string root_directory;
+ std::string relative_path;
+ std::string parent_path;
+ std::string filename;
+};
+
+const PathDecomposeTestcase PathTestCases[] =
+ {
+ {"", {}, "", "", "", "", "", ""}
+ , {".", {"."}, "", "", "", ".", "", "."}
+ , {"..", {".."}, "", "", "", "..", "", ".."}
+ , {"foo", {"foo"}, "", "", "", "foo", "", "foo"}
+ , {"/", {"/"}, "/", "", "/", "", "/", ""}
+ , {"/foo", {"/", "foo"}, "/", "", "/", "foo", "/", "foo"}
+ , {"foo/", {"foo", ""}, "", "", "", "foo/", "foo", ""}
+ , {"/foo/", {"/", "foo", ""}, "/", "", "/", "foo/", "/foo", ""}
+ , {"foo/bar", {"foo","bar"}, "", "", "", "foo/bar", "foo", "bar"}
+ , {"/foo//bar", {"/","foo","bar"}, "/", "", "/", "foo/bar", "/foo", "bar"}
+ , {"//net", {"/", "net"}, "/", "", "/", "net", "/", "net"}
+ , {"//net/foo", {"/", "net", "foo"}, "/", "", "/", "net/foo", "/net", "foo"}
+ , {"///foo///", {"/", "foo", ""}, "/", "", "/", "foo///", "///foo", ""}
+ , {"///foo///bar", {"/", "foo", "bar"}, "/", "", "/", "foo///bar", "///foo", "bar"}
+ , {"/.", {"/", "."}, "/", "", "/", ".", "/", "."}
+ , {"./", {".", ""}, "", "", "", "./", ".", ""}
+ , {"/..", {"/", ".."}, "/", "", "/", "..", "/", ".."}
+ , {"../", {"..", ""}, "", "", "", "../", "..", ""}
+ , {"foo/.", {"foo", "."}, "", "", "", "foo/.", "foo", "."}
+ , {"foo/..", {"foo", ".."}, "", "", "", "foo/..", "foo", ".."}
+ , {"foo/./", {"foo", ".", ""}, "", "", "", "foo/./", "foo/.", ""}
+ , {"foo/./bar", {"foo", ".", "bar"}, "", "", "", "foo/./bar", "foo/.", "bar"}
+ , {"foo/../", {"foo", "..", ""}, "", "", "", "foo/../", "foo/..", ""}
+ , {"foo/../bar", {"foo", "..", "bar"}, "", "", "", "foo/../bar", "foo/..", "bar"}
+ , {"c:", {"c:"}, "", "", "", "c:", "", "c:"}
+ , {"c:/", {"c:", ""}, "", "", "", "c:/", "c:", ""}
+ , {"c:foo", {"c:foo"}, "", "", "", "c:foo", "", "c:foo"}
+ , {"c:/foo", {"c:", "foo"}, "", "", "", "c:/foo", "c:", "foo"}
+ , {"c:foo/", {"c:foo", ""}, "", "", "", "c:foo/", "c:foo", ""}
+ , {"c:/foo/", {"c:", "foo", ""}, "", "", "", "c:/foo/", "c:/foo", ""}
+ , {"c:/foo/bar", {"c:", "foo", "bar"}, "", "", "", "c:/foo/bar", "c:/foo", "bar"}
+ , {"prn:", {"prn:"}, "", "", "", "prn:", "", "prn:"}
+ , {"c:\\", {"c:\\"}, "", "", "", "c:\\", "", "c:\\"}
+ , {"c:\\foo", {"c:\\foo"}, "", "", "", "c:\\foo", "", "c:\\foo"}
+ , {"c:foo\\", {"c:foo\\"}, "", "", "", "c:foo\\", "", "c:foo\\"}
+ , {"c:\\foo\\", {"c:\\foo\\"}, "", "", "", "c:\\foo\\", "", "c:\\foo\\"}
+ , {"c:\\foo/", {"c:\\foo", ""}, "", "", "", "c:\\foo/", "c:\\foo", ""}
+ , {"c:/foo\\bar", {"c:", "foo\\bar"}, "", "", "", "c:/foo\\bar", "c:", "foo\\bar"}
+ , {"//", {"/"}, "/", "", "/", "", "/", ""}
+ };
+
+void decompPathTest()
+{
+ using namespace fs;
+ for (auto const & TC : PathTestCases) {
+ CHECKPOINT(TC.raw.c_str());
+ fs::path p(TC.raw);
+ ASSERT(p == TC.raw);
+
+ ASSERT_EQ(p.root_path(), TC.root_path);
+ ASSERT_NEQ(p.has_root_path(), TC.root_path.empty());
+
+ ASSERT(p.root_name().native().empty())
+ << DISPLAY(p.root_name());
+ ASSERT_EQ(p.root_name(),TC.root_name);
+ ASSERT_NEQ(p.has_root_name(), TC.root_name.empty());
+
+ ASSERT_EQ(p.root_directory(), TC.root_directory);
+ ASSERT_NEQ(p.has_root_directory(), TC.root_directory.empty());
+
+ ASSERT_EQ(p.relative_path(), TC.relative_path);
+ ASSERT_NEQ(p.has_relative_path(), TC.relative_path.empty());
+
+ ASSERT_EQ(p.parent_path(), TC.parent_path);
+ ASSERT_NEQ(p.has_parent_path(), TC.parent_path.empty());
+
+ ASSERT_EQ(p.filename(), TC.filename);
+ ASSERT_NEQ(p.has_filename(), TC.filename.empty());
+
+ ASSERT_EQ(p.is_absolute(), p.has_root_directory());
+ ASSERT_NEQ(p.is_relative(), p.is_absolute());
+ if (p.empty())
+ ASSERT(p.is_relative());
+
+ ASSERT_COLLECTION_EQ_COMP(
+ p.begin(), p.end(),
+ TC.elements.begin(), TC.elements.end(),
+ ComparePathExact()
+ );
+ // check backwards
+
+ std::vector<fs::path> Parts;
+ for (auto it = p.end(); it != p.begin(); )
+ Parts.push_back(*--it);
+ ASSERT_COLLECTION_EQ_COMP(Parts.begin(), Parts.end(),
+ TC.elements.rbegin(), TC.elements.rend(),
+ ComparePathExact());
+ }
+}
+
+
+struct FilenameDecompTestcase
+{
+ std::string raw;
+ std::string filename;
+ std::string stem;
+ std::string extension;
+};
+
+const FilenameDecompTestcase FilenameTestCases[] =
+{
+ {"", "", "", ""}
+ , {".", ".", ".", ""}
+ , {"..", "..", "..", ""}
+ , {"/", "", "", ""}
+ , {"foo", "foo", "foo", ""}
+ , {"/foo/bar.txt", "bar.txt", "bar", ".txt"}
+ , {"foo..txt", "foo..txt", "foo.", ".txt"}
+ , {".profile", ".profile", ".profile", ""}
+ , {".profile.txt", ".profile.txt", ".profile", ".txt"}
+};
+
+
+void decompFilenameTest()
+{
+ using namespace fs;
+ for (auto const & TC : FilenameTestCases) {
+ CHECKPOINT(TC.raw.c_str());
+ fs::path p(TC.raw);
+ ASSERT_EQ(p, TC.raw);
+ ASSERT_NOEXCEPT(p.empty());
+
+ ASSERT_EQ(p.filename(), TC.filename);
+ ASSERT_NEQ(p.has_filename(), TC.filename.empty());
+
+ ASSERT_EQ(p.stem(), TC.stem);
+ ASSERT_NEQ(p.has_stem(), TC.stem.empty());
+
+ ASSERT_EQ(p.extension(), TC.extension);
+ ASSERT_NEQ(p.has_extension(), TC.extension.empty());
+ }
+}
+
+int main()
+{
+ decompPathTest();
+ decompFilenameTest();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path lexically_normal() const;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+int main() {
+ // clang-format off
+ struct {
+ std::string input;
+ std::string expect;
+ } TestCases[] = {
+ {"", ""},
+ {"/a/b/c", "/a/b/c"},
+ {"/a/b//c", "/a/b/c"},
+ {"foo/./bar/..", "foo/"},
+ {"foo/.///bar/../", "foo/"},
+ {"/a/b/", "/a/b/"},
+ {"a/b", "a/b"},
+ {"a/b/.", "a/b/"},
+ {"a/b/./", "a/b/"},
+ {"a/..", "."},
+ {".", "."},
+ {"./", "."},
+ {"./.", "."},
+ {"./..", ".."},
+ {"..", ".."},
+ {"../..", "../.."},
+ {"/../", "/"},
+ {"/../..", "/"},
+ {"/../../", "/"},
+ {"..", ".."},
+ {"../", ".."},
+ {"/a/b/c/../", "/a/b/"},
+ {"/a/b/./", "/a/b/"},
+ {"/a/b/c/../d", "/a/b/d"},
+ {"/a/b/c/../d/", "/a/b/d/"},
+ {"//a/", "/a/"},
+ {"//a/b/", "/a/b/"},
+ {"//a/b/.", "/a/b/"},
+ {"//a/..", "/"},
+ ///===---------------------------------------------------------------===//
+ /// Tests specifically for the clauses under [fs.path.generic]p6
+ ///===---------------------------------------------------------------===//
+ // p1: If the path is empty, stop.
+ {"", ""},
+ // p2: Replace each slash character in the root-name with a preferred
+ // separator.
+ {"NO_ROOT_NAME_ON_LINUX", "NO_ROOT_NAME_ON_LINUX"},
+ // p3: Replace each directory-separator with a preferred-separator.
+ // [ Note: The generic pathname grammar ([fs.path.generic]) defines
+ // directory-separator as one or more slashes and preferred-separators.
+ // — end note ]
+ {"/", "/"},
+ {"//", "/"},
+ {"///", "/"},
+ {"a/b", "a/b"},
+ {"a//b", "a/b"},
+ {"a///b", "a/b"},
+ {"a/b/", "a/b/"},
+ {"a/b//", "a/b/"},
+ {"a/b///", "a/b/"},
+ {"///a////b//////", "/a/b/"},
+ // p4: Remove each dot filename and any immediately following directory
+ // separators
+ {"foo/.", "foo/"},
+ {"foo/./bar/.", "foo/bar/"},
+ {"./foo/././bar/./", "foo/bar/"},
+ {".///foo//.////./bar/.///", "foo/bar/"},
+ // p5: As long as any appear, remove a non-dot-dot filename immediately
+ // followed by a directory-separator and a dot-dot filename, along with
+ // any immediately following directory separator.
+ {"foo/..", "."},
+ {"foo/../", "."},
+ {"foo/bar/..", "foo/"},
+ {"foo/bar/../", "foo/"},
+ {"foo/bar/../..", "."},
+ {"foo/bar/../../", "."},
+ {"foo/bar/baz/../..", "foo/"},
+ {"foo/bar/baz/../../", "foo/"},
+ {"foo/bar/./..", "foo/"},
+ {"foo/bar/./../", "foo/"},
+ // p6: If there is a root-directory, remove all dot-dot filenames and any
+ // directory-separators immediately following them. [ Note: These dot-dot
+ // filenames attempt to refer to nonexistent parent directories. — end note ]
+ {"/..", "/"},
+ {"/../", "/"},
+ {"/foo/../..", "/"},
+ {"/../foo", "/foo"},
+ {"/../foo/../..", "/"},
+ // p7: If the last filename is dot-dot, remove any trailing
+ // directory-separator.
+ {"../", ".."},
+ {"../../", "../.."},
+ {"foo/../bar/../..///", ".."},
+ {"foo/../bar/..//..///../", "../.."},
+ // p8: If the path is empty, add a dot
+ {".", "."},
+ {"./", "."},
+ {"foo/..", "."}
+ };
+ // clang-format on
+ int ID = 0;
+ bool Failed = false;
+ for (auto& TC : TestCases) {
+ ++ID;
+ fs::path p(TC.input);
+ const fs::path output = p.lexically_normal();
+ if (!PathEq(output, TC.expect)) {
+ Failed = true;
+ std::cerr << "TEST CASE #" << ID << " FAILED: \n";
+ std::cerr << " Input: '" << TC.input << "'\n";
+ std::cerr << " Expected: '" << TC.expect << "'\n";
+ std::cerr << " Output: '" << output.native() << "'";
+ std::cerr << std::endl;
+ }
+ }
+ return Failed;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path lexically_relative(const path& p) const;
+// path lexically_proximate(const path& p) const;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+int main() {
+ // clang-format off
+ struct {
+ std::string input;
+ std::string base;
+ std::string expect;
+ } TestCases[] = {
+ {"", "", "."},
+ {"/", "a", ""},
+ {"a", "/", ""},
+ {"//net", "a", ""},
+ {"a", "//net", ""},
+ {"//net/", "//net", ""},
+ {"//net", "//net/", ".."},
+ {"//base", "a", ""},
+ {"a", "a", "."},
+ {"a/b", "a/b", "."},
+ {"a/b/c/", "a/b/c/", "."},
+ {"//net", "//net", "."},
+ {"//net/", "//net/", "."},
+ {"//net/a/b", "//net/a/b", "."},
+ {"/a/d", "/a/b/c", "../../d"},
+ {"/a/b/c", "/a/d", "../b/c"},
+ {"a/b/c", "a", "b/c"},
+ {"a/b/c", "a/b/c/x/y", "../.."},
+ {"a/b/c", "a/b/c", "."},
+ {"a/b", "c/d", "../../a/b"}
+ };
+ // clang-format on
+ int ID = 0;
+ bool Failed = false;
+ for (auto& TC : TestCases) {
+ ++ID;
+ const fs::path p(TC.input);
+ const fs::path output = p.lexically_relative(TC.base);
+ auto ReportErr = [&](const char* Testing, fs::path const& Output,
+ fs::path const& Expected) {
+ Failed = true;
+ std::cerr << "TEST CASE #" << ID << " FAILED: \n";
+ std::cerr << " Testing: " << Testing << "\n";
+ std::cerr << " Input: '" << TC.input << "'\n";
+ std::cerr << " Base: '" << TC.base << "'\n";
+ std::cerr << " Expected: '" << Expected << "'\n";
+ std::cerr << " Output: '" << Output.native() << "'";
+ std::cerr << std::endl;
+ };
+ if (!PathEq(output, TC.expect))
+ ReportErr("path::lexically_relative", output, TC.expect);
+ const fs::path proximate_output = p.lexically_proximate(TC.base);
+ // [path.gen] lexically_proximate
+ // Returns: If the value of lexically_relative(base) is not an empty path,
+ // return it.Otherwise return *this.
+ const fs::path proximate_expected = output.native().empty() ? p
+ : output;
+ if (!PathEq(proximate_expected, proximate_output))
+ ReportErr("path::lexically_proximate", proximate_output, proximate_expected);
+ }
+ return Failed;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class ECharT, class Traits = char_traits<ECharT>,
+// class Allocator = allocator<ECharT>>
+// basic_string<ECharT, Traits, Allocator>
+// generic_string(const Allocator& a = Allocator()) const;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "min_allocator.h"
+#include "filesystem_test_helper.hpp"
+
+MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+
+
+// generic_string<C, T, A> forwards to string<C, T, A>. Tests for
+// string<C, T, A>() are in "path.native.op/string_alloc.pass.cpp".
+// generic_string is minimally tested here.
+int main()
+{
+ using namespace fs;
+ using CharT = wchar_t;
+ using Traits = std::char_traits<CharT>;
+ using Alloc = malloc_allocator<CharT>;
+ using Str = std::basic_string<CharT, Traits, Alloc>;
+ const wchar_t* expect = longString;
+ const path p((const char*)longString);
+ {
+ DisableAllocationGuard g;
+ Alloc a;
+ Alloc::disable_default_constructor = true;
+ Str s = p.generic_string<wchar_t, Traits, Alloc>(a);
+ assert(s == expect);
+ assert(Alloc::alloc_count > 0);
+ assert(Alloc::outstanding_alloc() == 1);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// std::string generic_string() const;
+// std::wstring generic_wstring() const;
+// std::u8string generic_u8string() const;
+// std::u16string generic_u16string() const;
+// std::u32string generic_u32string() const;
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "min_allocator.h"
+#include "filesystem_test_helper.hpp"
+
+MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+
+int main()
+{
+ using namespace fs;
+ auto const& MS = longString;
+ const char* value = longString;
+ const path p(value);
+ {
+ std::string s = p.generic_string();
+ assert(s == value);
+ }
+ {
+ std::string s = p.generic_u8string();
+ assert(s == (const char*)MS);
+ }
+ {
+ std::wstring s = p.generic_wstring();
+ assert(s == (const wchar_t*)MS);
+ }
+ {
+ std::u16string s = p.generic_u16string();
+ assert(s == (const char16_t*)MS);
+ }
+ {
+ std::u32string s = p.generic_u32string();
+ assert(s == (const char32_t*)MS);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// void clear() noexcept
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+int main() {
+ using namespace fs;
+ {
+ path p;
+ ASSERT_NOEXCEPT(p.clear());
+ ASSERT_SAME_TYPE(void, decltype(p.clear()));
+ p.clear();
+ assert(p.empty());
+ }
+ {
+ const path p("/foo/bar/baz");
+ path p2(p);
+ assert(p == p2);
+ p2.clear();
+ assert(p2.empty());
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& make_preferred()
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+struct MakePreferredTestcase {
+ const char* value;
+};
+
+const MakePreferredTestcase TestCases[] =
+ {
+ {""}
+ , {"hello_world"}
+ , {"/"}
+ , {"/foo/bar/baz/"}
+ , {"\\"}
+ , {"\\foo\\bar\\baz\\"}
+ , {"\\foo\\/bar\\/baz\\"}
+ };
+
+int main()
+{
+ // This operation is an identity operation on linux.
+ using namespace fs;
+ for (auto const & TC : TestCases) {
+ path p(TC.value);
+ assert(p == TC.value);
+ path& Ref = (p.make_preferred());
+ assert(p.native() == TC.value);
+ assert(&Ref == &p);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& remove_filename()
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+#include "verbose_assert.h"
+
+struct RemoveFilenameTestcase {
+ const char* value;
+ const char* expect;
+};
+
+const RemoveFilenameTestcase TestCases[] =
+ {
+ {"", ""}
+ , {"/", "/"}
+ , {"//", "//"}
+ , {"///", "///"}
+ , {"\\", ""}
+ , {".", ""}
+ , {"..", ""}
+ , {"/foo", "/"}
+ , {"foo/bar", "foo/"}
+ , {"foo/", "foo/"}
+ , {"//foo", "//"}
+ , {"//foo/", "//foo/"}
+ , {"//foo///", "//foo///"}
+ , {"///foo", "///"}
+ , {"///foo/", "///foo/"}
+ , {"/foo/", "/foo/"}
+ , {"/foo/.", "/foo/"}
+ , {"/foo/..", "/foo/"}
+ , {"/foo/////", "/foo/////"}
+ , {"/foo\\\\", "/"}
+ , {"/foo//\\/", "/foo//\\/"}
+ , {"///foo", "///"}
+ , {"file.txt", ""}
+ , {"bar/../baz/./file.txt", "bar/../baz/./"}
+ };
+
+int main()
+{
+ using namespace fs;
+ for (auto const & TC : TestCases) {
+ path const p_orig(TC.value);
+ path p(p_orig);
+ assert(p == TC.value);
+ path& Ref = (p.remove_filename());
+ ASSERT_EQ(p, TC.expect) << DISPLAY(p_orig);
+ assert(&Ref == &p);
+ assert(!p.has_filename());
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& replace_extension(path const& p = path())
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+struct ReplaceExtensionTestcase {
+ const char* value;
+ const char* expect;
+ const char* extension;
+};
+
+const ReplaceExtensionTestcase TestCases[] =
+ {
+ {"", "", ""}
+ , {"foo.cpp", "foo", ""}
+ , {"foo.cpp", "foo.", "."}
+ , {"foo..cpp", "foo..txt", "txt"}
+ , {"", ".txt", "txt"}
+ , {"", ".txt", ".txt"}
+ , {"/foo", "/foo.txt", ".txt"}
+ , {"/foo", "/foo.txt", "txt"}
+ , {"/foo.cpp", "/foo.txt", ".txt"}
+ , {"/foo.cpp", "/foo.txt", "txt"}
+ };
+const ReplaceExtensionTestcase NoArgCases[] =
+ {
+ {"", "", ""}
+ , {"foo", "foo", ""}
+ , {"foo.cpp", "foo", ""}
+ , {"foo..cpp", "foo.", ""}
+};
+
+int main()
+{
+ using namespace fs;
+ for (auto const & TC : TestCases) {
+ path p(TC.value);
+ assert(p == TC.value);
+ path& Ref = (p.replace_extension(TC.extension));
+ assert(p == TC.expect);
+ assert(&Ref == &p);
+ }
+ for (auto const& TC : NoArgCases) {
+ path p(TC.value);
+ assert(p == TC.value);
+ path& Ref = (p.replace_extension());
+ assert(p == TC.expect);
+ assert(&Ref == &p);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// path& replace_filename()
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+#include "assert_checkpoint.h"
+#include "verbose_assert.h"
+
+struct ReplaceFilenameTestcase {
+ const char* value;
+ const char* expect;
+ const char* filename;
+};
+
+const ReplaceFilenameTestcase TestCases[] =
+ {
+ {"/foo", "/bar", "bar"}
+ , {"/foo", "/", ""}
+ , {"foo", "bar", "bar"}
+ , {"/", "/bar", "bar"}
+ , {"\\", "bar", "bar"}
+ , {"///", "///bar", "bar"}
+ , {"\\\\", "bar", "bar"}
+ , {"\\/\\", "\\/bar", "bar"}
+ , {".", "bar", "bar"}
+ , {"..", "bar", "bar"}
+ , {"/foo\\baz/bong/", "/foo\\baz/bong/bar", "bar"}
+ , {"/foo\\baz/bong", "/foo\\baz/bar", "bar"}
+ };
+
+int main()
+{
+ using namespace fs;
+ for (auto const & TC : TestCases) {
+ path p(TC.value);
+ ASSERT_EQ(p, TC.value);
+ path& Ref = (p.replace_filename(TC.filename));
+ ASSERT_EQ(p, TC.expect)
+ << DISPLAY(TC.value)
+ << DISPLAY(TC.filename);
+ assert(&Ref == &p);
+ // Tests Effects "as-if": remove_filename() append(filename)
+ {
+ path p2(TC.value);
+ path replace(TC.filename);
+ p2.remove_filename();
+ p2 /= replace;
+ ASSERT_EQ(p, p2);
+ }
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// void swap(path& rhs) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+struct SwapTestcase {
+ const char* value1;
+ const char* value2;
+};
+
+#define LONG_STR1 "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG"
+#define LONG_STR2 "_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2"
+const SwapTestcase TestCases[] =
+ {
+ {"", ""}
+ , {"shortstr", LONG_STR1}
+ , {LONG_STR1, "shortstr"}
+ , {LONG_STR1, LONG_STR2}
+ };
+#undef LONG_STR1
+#undef LONG_STR2
+
+int main()
+{
+ using namespace fs;
+ {
+ path p;
+ ASSERT_NOEXCEPT(p.swap(p));
+ ASSERT_SAME_TYPE(void, decltype(p.swap(p)));
+ }
+ for (auto const & TC : TestCases) {
+ path p1(TC.value1);
+ path p2(TC.value2);
+ {
+ DisableAllocationGuard g;
+ p1.swap(p2);
+ }
+ assert(p1 == TC.value2);
+ assert(p2 == TC.value1);
+ {
+ DisableAllocationGuard g;
+ p1.swap(p2);
+ }
+ assert(p1 == TC.value1);
+ assert(p2 == TC.value2);
+ }
+ // self-swap
+ {
+ const char* Val = "aoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeu";
+ path p1(Val);
+ assert(p1 == Val);
+ {
+ DisableAllocationGuard g;
+ p1.swap(p1);
+ }
+ assert(p1 == Val);
+ }
+}
--- /dev/null
+
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// const value_type* c_str() const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.hpp"
+
+
+int main()
+{
+ using namespace fs;
+ const char* const value = "hello world";
+ const std::string str_value = value;
+ { // Check signature
+ path p(value);
+ ASSERT_SAME_TYPE(path::value_type const*, decltype(p.c_str()));
+ ASSERT_NOEXCEPT(p.c_str());
+ }
+ {
+ path p(value);
+ assert(p.c_str() == str_value);
+ assert(p.native().c_str() == p.c_str());
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// std::string string() const;
+// std::wstring wstring() const;
+// std::u8string u8string() const;
+// std::u16string u16string() const;
+// std::u32string u32string() const;
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "min_allocator.h"
+#include "filesystem_test_helper.hpp"
+
+
+MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+
+int main()
+{
+ using namespace fs;
+ auto const& MS = longString;
+ const char* value = longString;
+ const path p(value);
+ {
+ std::string s = p.string();
+ assert(s == value);
+ }
+ {
+ std::string s = p.u8string();
+ assert(s == (const char*)MS);
+ }
+ {
+ std::wstring s = p.wstring();
+ assert(s == (const wchar_t*)MS);
+ }
+ {
+ std::u16string s = p.u16string();
+ assert(s == (const char16_t*)MS);
+ }
+ {
+ std::u32string s = p.u32string();
+ assert(s == (const char32_t*)MS);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// const string_type& native() const noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.hpp"
+
+
+int main()
+{
+ using namespace fs;
+ const char* const value = "hello world";
+ { // Check signature
+ path p(value);
+ ASSERT_SAME_TYPE(path::string_type const&, decltype(p.native()));
+ ASSERT_NOEXCEPT(p.native());
+ }
+ { // native() is tested elsewhere
+ path p(value);
+ assert(p.native() == value);
+ }
+}
--- /dev/null
+
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// operator string_type() const;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.hpp"
+
+
+int main()
+{
+ using namespace fs;
+ using string_type = path::string_type;
+ const char* const value = "hello world";
+ { // Check signature
+ path p(value);
+ static_assert(std::is_convertible<path, string_type>::value, "");
+ static_assert(std::is_constructible<string_type, path>::value, "");
+ ASSERT_SAME_TYPE(string_type, decltype(p.operator string_type()));
+ ASSERT_NOT_NOEXCEPT(p.operator string_type());
+ }
+ {
+ path p(value);
+ assert(p.native() == value);
+ string_type s = p;
+ assert(s == value);
+ assert(p == value);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class ECharT, class Traits = char_traits<ECharT>,
+// class Allocator = allocator<ECharT>>
+// basic_string<ECharT, Traits, Allocator>
+// string(const Allocator& a = Allocator()) const;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "min_allocator.h"
+#include "filesystem_test_helper.hpp"
+
+
+// the SSO is always triggered for strings of size 2.
+MultiStringType shortString = MKSTR("a");
+MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+
+template <class CharT>
+void doShortStringTest(MultiStringType const& MS) {
+ using namespace fs;
+ using Ptr = CharT const*;
+ using Str = std::basic_string<CharT>;
+ using Alloc = std::allocator<CharT>;
+ Ptr value = MS;
+ const path p((const char*)MS);
+ {
+ DisableAllocationGuard g;
+ Str s = p.string<CharT>();
+ assert(s == value);
+ Str s2 = p.string<CharT>(Alloc{});
+ assert(s2 == value);
+ }
+ using MAlloc = malloc_allocator<CharT>;
+ MAlloc::reset();
+ {
+ using Traits = std::char_traits<CharT>;
+ using AStr = std::basic_string<CharT, Traits, MAlloc>;
+ DisableAllocationGuard g;
+ AStr s = p.string<CharT, Traits, MAlloc>();
+ assert(s == value);
+ assert(MAlloc::alloc_count == 0);
+ assert(MAlloc::outstanding_alloc() == 0);
+ }
+ MAlloc::reset();
+ { // Other allocator - provided copy
+ using Traits = std::char_traits<CharT>;
+ using AStr = std::basic_string<CharT, Traits, MAlloc>;
+ DisableAllocationGuard g;
+ MAlloc a;
+ // don't allow another allocator to be default constructed.
+ MAlloc::disable_default_constructor = true;
+ AStr s = p.string<CharT, Traits, MAlloc>(a);
+ assert(s == value);
+ assert(MAlloc::alloc_count == 0);
+ assert(MAlloc::outstanding_alloc() == 0);
+ }
+ MAlloc::reset();
+}
+
+template <class CharT>
+void doLongStringTest(MultiStringType const& MS) {
+ using namespace fs;
+ using Ptr = CharT const*;
+ using Str = std::basic_string<CharT>;
+ Ptr value = MS;
+ const path p((const char*)MS);
+ { // Default allocator
+ using Alloc = std::allocator<CharT>;
+ Str s = p.string<CharT>();
+ assert(s == value);
+ Str s2 = p.string<CharT>(Alloc{});
+ assert(s2 == value);
+ }
+ using MAlloc = malloc_allocator<CharT>;
+ MAlloc::reset();
+ { // Other allocator - default construct
+ using Traits = std::char_traits<CharT>;
+ using AStr = std::basic_string<CharT, Traits, MAlloc>;
+ DisableAllocationGuard g;
+ AStr s = p.string<CharT, Traits, MAlloc>();
+ assert(s == value);
+ assert(MAlloc::alloc_count > 0);
+ assert(MAlloc::outstanding_alloc() == 1);
+ }
+ MAlloc::reset();
+ { // Other allocator - provided copy
+ using Traits = std::char_traits<CharT>;
+ using AStr = std::basic_string<CharT, Traits, MAlloc>;
+ DisableAllocationGuard g;
+ MAlloc a;
+ // don't allow another allocator to be default constructed.
+ MAlloc::disable_default_constructor = true;
+ AStr s = p.string<CharT, Traits, MAlloc>(a);
+ assert(s == value);
+ assert(MAlloc::alloc_count > 0);
+ assert(MAlloc::outstanding_alloc() == 1);
+ }
+ MAlloc::reset();
+ /////////////////////////////////////////////////////////////////////////////
+}
+
+int main()
+{
+ using namespace fs;
+ {
+ auto const& S = shortString;
+ doShortStringTest<char>(S);
+ doShortStringTest<wchar_t>(S);
+ doShortStringTest<char16_t>(S);
+ doShortStringTest<char32_t>(S);
+ }
+ {
+ auto const& S = longString;
+ doLongStringTest<char>(S);
+ doLongStringTest<wchar_t>(S);
+ doLongStringTest<char16_t>(S);
+ doLongStringTest<char32_t>(S);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+//-------------------------------
+// 8.4.10 path query [path.query]
+//-------------------------------
+// bool empty() const noexcept;
+// bool has_root_path() const;
+// bool has_root_name() const;
+// bool has_root_directory() const;
+// bool has_relative_path() const;
+// bool has_parent_path() const;
+// bool has_filename() const;
+// bool has_stem() const;
+// bool has_extension() const;
+// bool is_absolute() const;
+// bool is_relative() const;
+
+// tested in path.decompose
+int main() {}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path operator/(path const&, path const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "filesystem_test_helper.hpp"
+
+
+// This is mainly tested via the member append functions.
+int main()
+{
+ using namespace fs;
+ path p1("abc");
+ path p2("def");
+ path p3 = p1 / p2;
+ assert(p3 == "abc/def");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// The comparison operators are tested as part of [path.compare]
+// in class.path/path.members/path.compare.pass.cpp
+int main() {}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// The "hash_value" function is tested as part of [path.compare]
+// in class.path/path.members/path.compare.pass.cpp
+int main() {}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// template <class Source>
+// path u8path(Source const&);
+// template <class InputIter>
+// path u8path(InputIter, InputIter);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+int main()
+{
+ using namespace fs;
+ const char* In1 = "abcd/efg";
+ const std::string In2(In1);
+ const auto In3 = In2.begin();
+ const auto In3End = In2.end();
+ {
+ path p = fs::u8path(In1);
+ assert(p == In1);
+ }
+ {
+ path p = fs::u8path(In2);
+ assert(p == In1);
+ }
+ {
+ path p = fs::u8path(In3);
+ assert(p == In1);
+ }
+ {
+ path p = fs::u8path(In3, In3End);
+ assert(p == In1);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class charT, class traits>
+// basic_ostream<charT, traits>&
+// operator<<(basic_ostream<charT, traits>& os, const path& p);
+//
+// template <class charT, class traits>
+// basic_istream<charT, traits>&
+// operator>>(basic_istream<charT, traits>& is, path& p)
+//
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <sstream>
+#include <cassert>
+#include <iostream>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
+MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
+
+
+
+template <class CharT>
+void doIOTest() {
+ using namespace fs;
+ using Ptr = const CharT*;
+ using StrStream = std::basic_stringstream<CharT>;
+ const Ptr E = OutStr;
+ const path p((const char*)InStr);
+ StrStream ss;
+ { // test output
+ auto& ret = (ss << p);
+ assert(ss.str() == E);
+ assert(&ret == &ss);
+ }
+ { // test input
+ path p_in;
+ auto& ret = ss >> p_in;
+ assert(p_in.native() == (const char*)InStr);
+ assert(&ret == &ss);
+ }
+}
+
+namespace impl {
+using namespace fs;
+
+template <class Stream, class Tp, class = decltype(std::declval<Stream&>() << std::declval<Tp&>())>
+std::true_type is_ostreamable_imp(int);
+
+template <class Stream, class Tp>
+std::false_type is_ostreamable_imp(long);
+
+template <class Stream, class Tp, class = decltype(std::declval<Stream&>() >> std::declval<Tp&>())>
+std::true_type is_istreamable_imp(int);
+
+template <class Stream, class Tp>
+std::false_type is_istreamable_imp(long);
+
+
+} // namespace impl
+
+template <class Stream, class Tp>
+struct is_ostreamable : decltype(impl::is_ostreamable_imp<Stream, Tp>(0)) {};
+template <class Stream, class Tp>
+struct is_istreamable : decltype(impl::is_istreamable_imp<Stream, Tp>(0)) {};
+
+void test_LWG2989() {
+ static_assert(!is_ostreamable<decltype(std::cout), std::wstring>::value, "");
+ static_assert(!is_ostreamable<decltype(std::wcout), std::string>::value, "");
+ static_assert(!is_istreamable<decltype(std::cin), std::wstring>::value, "");
+ static_assert(!is_istreamable<decltype(std::wcin), std::string>::value, "");
+}
+
+int main() {
+ doIOTest<char>();
+ doIOTest<wchar_t>();
+ //doIOTest<char16_t>();
+ //doIOTest<char32_t>();
+ test_LWG2989();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// template <class charT, class traits>
+// basic_ostream<charT, traits>&
+// operator<<(basic_ostream<charT, traits>& os, const path& p);
+//
+// template <class charT, class traits>
+// basic_istream<charT, traits>&
+// operator>>(basic_istream<charT, traits>& is, path& p)
+//
+
+// TODO(EricWF) This test fails because "std::quoted" fails to compile
+// for char16_t and char32_t types. Combine with path.io.pass.cpp when this
+// passes.
+// XFAIL: *
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <sstream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
+MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
+
+template <class CharT>
+void doIOTest() {
+ using namespace fs;
+ using Ptr = const CharT*;
+ using StrStream = std::basic_stringstream<CharT>;
+ const char* const InCStr = InStr;
+ const Ptr E = OutStr;
+ const path p((const char*)InStr);
+ StrStream ss;
+ { // test output
+ auto& ret = (ss << p);
+ assert(ss.str() == E);
+ assert(&ret == &ss);
+ }
+ { // test input
+ path p_in;
+ auto& ret = ss >> p_in;
+ assert(p_in.native() == (const char*)InStr);
+ assert(&ret == &ss);
+ }
+}
+
+
+int main() {
+ doIOTest<char16_t>();
+ doIOTest<char32_t>();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void swap(path& lhs, path& rhs) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+// NOTE: this is tested in path.members/path.modifiers via the member swap.
+int main()
+{
+ using namespace fs;
+ const char* value1 = "foo/bar/baz";
+ const char* value2 = "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG";
+ path p1(value1);
+ path p2(value2);
+ {
+ using namespace std; using namespace fs;
+ ASSERT_NOEXCEPT(swap(p1, p2));
+ ASSERT_SAME_TYPE(void, decltype(swap(p1, p2)));
+ }
+ {
+ DisableAllocationGuard g;
+ using namespace std;
+ using namespace fs;
+ swap(p1, p2);
+ assert(p1.native() == value2);
+ assert(p2.native() == value1);
+ swap(p1, p2);
+ assert(p1.native() == value1);
+ assert(p2.native() == value2);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path
+
+// typedef ... value_type;
+// typedef basic_string<value_type> string_type;
+// static constexpr value_type preferred_separator = ...;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+int main() {
+ using namespace fs;
+ ASSERT_SAME_TYPE(path::value_type, char);
+ ASSERT_SAME_TYPE(path::string_type, std::basic_string<path::value_type>);
+ {
+ ASSERT_SAME_TYPE(const path::value_type, decltype(path::preferred_separator));
+ static_assert(path::preferred_separator == '/', "");
+ // Make preferred_separator ODR used by taking its address.
+ const char* dummy = &path::preferred_separator;
+ ((void)dummy);
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// recursive_recursive_directory_iterator(recursive_recursive_directory_iterator const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_copy_construct_tests)
+
+TEST_CASE(test_constructor_signature)
+{
+ using D = recursive_directory_iterator;
+ static_assert(std::is_copy_constructible<D>::value, "");
+ //static_assert(!std::is_nothrow_copy_constructible<D>::value, "");
+}
+
+TEST_CASE(test_copy_end_iterator)
+{
+ const recursive_directory_iterator endIt;
+ recursive_directory_iterator it(endIt);
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(test_copy_valid_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+ const recursive_directory_iterator endIt{};
+
+ // build 'it' up with "interesting" non-default state so we can test
+ // that it gets copied. We want to get 'it' into a state such that:
+ // it.options() != directory_options::none
+ // it.depth() != 0
+ // it.recursion_pending() != true
+ const directory_options opts = directory_options::skip_permission_denied;
+ recursive_directory_iterator it(testDir, opts);
+ TEST_REQUIRE(it != endIt);
+ while (it.depth() == 0) {
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ }
+ it.disable_recursion_pending();
+ TEST_CHECK(it.options() == opts);
+ TEST_CHECK(it.depth() == 1);
+ TEST_CHECK(it.recursion_pending() == false);
+ const path entry = *it;
+
+ // OPERATION UNDER TEST //
+ const recursive_directory_iterator it2(it);
+ // ------------------- //
+
+ TEST_REQUIRE(it2 == it);
+ TEST_CHECK(*it2 == entry);
+ TEST_CHECK(it2.depth() == 1);
+ TEST_CHECK(it2.recursion_pending() == false);
+ TEST_CHECK(it != endIt);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// recursive_directory_iterator& operator=(recursive_directory_iterator const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_copy_assign_tests)
+
+recursive_directory_iterator createInterestingIterator()
+ // Create an "interesting" iterator where all fields are
+ // in a non-default state. The returned 'it' is in a
+ // state such that:
+ // it.options() == directory_options::skip_permission_denied
+ // it.depth() == 1
+ // it.recursion_pending() == true
+{
+ const path testDir = StaticEnv::Dir;
+ const recursive_directory_iterator endIt;
+ recursive_directory_iterator it(testDir,
+ directory_options::skip_permission_denied);
+ TEST_ASSERT(it != endIt);
+ while (it.depth() != 1) {
+ ++it;
+ TEST_ASSERT(it != endIt);
+ }
+ TEST_ASSERT(it.depth() == 1);
+ it.disable_recursion_pending();
+ return it;
+}
+
+
+recursive_directory_iterator createDifferentInterestingIterator()
+ // Create an "interesting" iterator where all fields are
+ // in a non-default state. The returned 'it' is in a
+ // state such that:
+ // it.options() == directory_options::follow_directory_symlink
+ // it.depth() == 2
+ // it.recursion_pending() == false
+{
+ const path testDir = StaticEnv::Dir;
+ const recursive_directory_iterator endIt;
+ recursive_directory_iterator it(testDir,
+ directory_options::follow_directory_symlink);
+ TEST_ASSERT(it != endIt);
+ while (it.depth() != 2) {
+ ++it;
+ TEST_ASSERT(it != endIt);
+ }
+ TEST_ASSERT(it.depth() == 2);
+ return it;
+}
+
+TEST_CASE(test_assignment_signature) {
+ using D = recursive_directory_iterator;
+ static_assert(std::is_copy_assignable<D>::value, "");
+}
+
+TEST_CASE(test_copy_to_end_iterator)
+{
+ const recursive_directory_iterator endIt;
+
+ const recursive_directory_iterator from = createInterestingIterator();
+ const path entry = *from;
+
+ recursive_directory_iterator to;
+ to = from;
+ TEST_REQUIRE(to == from);
+ TEST_CHECK(*to == entry);
+ TEST_CHECK(to.options() == from.options());
+ TEST_CHECK(to.depth() == from.depth());
+ TEST_CHECK(to.recursion_pending() == from.recursion_pending());
+}
+
+
+TEST_CASE(test_copy_from_end_iterator)
+{
+ const recursive_directory_iterator from;
+ recursive_directory_iterator to = createInterestingIterator();
+
+ to = from;
+ TEST_REQUIRE(to == from);
+ TEST_CHECK(to == recursive_directory_iterator{});
+}
+
+TEST_CASE(test_copy_valid_iterator)
+{
+ const recursive_directory_iterator endIt;
+
+ const recursive_directory_iterator it = createInterestingIterator();
+ const path entry = *it;
+
+ recursive_directory_iterator it2 = createDifferentInterestingIterator();
+ TEST_REQUIRE(it2 != it);
+ TEST_CHECK(it2.options() != it.options());
+ TEST_CHECK(it2.depth() != it.depth());
+ TEST_CHECK(it2.recursion_pending() != it.recursion_pending());
+ TEST_CHECK(*it2 != entry);
+
+ it2 = it;
+ TEST_REQUIRE(it2 == it);
+ TEST_CHECK(it2.options() == it.options());
+ TEST_CHECK(it2.depth() == it.depth());
+ TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
+ TEST_CHECK(*it2 == entry);
+}
+
+TEST_CASE(test_returns_reference_to_self)
+{
+ const recursive_directory_iterator it;
+ recursive_directory_iterator it2;
+ recursive_directory_iterator& ref = (it2 = it);
+ TEST_CHECK(&ref == &it2);
+}
+
+TEST_CASE(test_self_copy)
+{
+ // Create two non-equal iterators that have exactly the same state.
+ recursive_directory_iterator it = createInterestingIterator();
+ recursive_directory_iterator it2 = createInterestingIterator();
+ TEST_CHECK(it != it2);
+ TEST_CHECK(it2.options() == it.options());
+ TEST_CHECK(it2.depth() == it.depth());
+ TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
+ TEST_CHECK(*it2 == *it);
+
+ // perform a self-copy and check that the state still matches the
+ // other unmodified iterator.
+ recursive_directory_iterator const& cit = it;
+ it = cit;
+ TEST_CHECK(it2.options() == it.options());
+ TEST_CHECK(it2.depth() == it.depth());
+ TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
+ TEST_CHECK(*it2 == *it);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class directory_iterator
+
+//
+// explicit recursive_directory_iterator(const path& p);
+// recursive_directory_iterator(const path& p, directory_options options);
+// recursive_directory_iterator(const path& p, error_code& ec);
+// recursive_directory_iterator(const path& p, directory_options options, error_code& ec);
+
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+using RDI = recursive_directory_iterator;
+
+TEST_SUITE(recursive_directory_iterator_constructor_tests)
+
+TEST_CASE(test_constructor_signatures)
+{
+ using D = recursive_directory_iterator;
+
+ // explicit directory_iterator(path const&);
+ static_assert(!std::is_convertible<path, D>::value, "");
+ static_assert(std::is_constructible<D, path>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path>::value, "");
+
+ // directory_iterator(path const&, error_code&)
+ static_assert(std::is_constructible<D, path,
+ std::error_code&>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path,
+ std::error_code&>::value, "");
+
+ // directory_iterator(path const&, directory_options);
+ static_assert(std::is_constructible<D, path, directory_options>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
+
+ // directory_iterator(path const&, directory_options, error_code&)
+ static_assert(std::is_constructible<D, path, directory_options, std::error_code&>::value, "");
+ static_assert(!std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, "");
+}
+
+TEST_CASE(test_construction_from_bad_path)
+{
+ std::error_code ec;
+ directory_options opts = directory_options::none;
+ const RDI endIt;
+
+ const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink };
+ for (path const& testPath : testPaths)
+ {
+ {
+ RDI it(testPath, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ RDI it(testPath, opts, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ TEST_CHECK_THROW(filesystem_error, RDI(testPath));
+ TEST_CHECK_THROW(filesystem_error, RDI(testPath, opts));
+ }
+ }
+}
+
+TEST_CASE(access_denied_test_case)
+{
+ using namespace fs;
+ scoped_test_env env;
+ path const testDir = env.make_env_path("dir1");
+ path const testFile = testDir / "testFile";
+ env.create_dir(testDir);
+ env.create_file(testFile, 42);
+
+ // Test that we can iterator over the directory before changing the perms
+ {
+ RDI it(testDir);
+ TEST_REQUIRE(it != RDI{});
+ }
+
+ // Change the permissions so we can no longer iterate
+ permissions(testDir, perms::none);
+
+ // Check that the construction fails when skip_permissions_denied is
+ // not given.
+ {
+ std::error_code ec;
+ RDI it(testDir, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == RDI{});
+ }
+ // Check that construction does not report an error when
+ // 'skip_permissions_denied' is given.
+ {
+ std::error_code ec;
+ RDI it(testDir, directory_options::skip_permission_denied, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it == RDI{});
+ }
+}
+
+
+TEST_CASE(access_denied_to_file_test_case)
+{
+ using namespace fs;
+ scoped_test_env env;
+ path const testFile = env.make_env_path("file1");
+ env.create_file(testFile, 42);
+
+ // Change the permissions so we can no longer iterate
+ permissions(testFile, perms::none);
+
+ // Check that the construction fails when skip_permissions_denied is
+ // not given.
+ {
+ std::error_code ec;
+ RDI it(testFile, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == RDI{});
+ }
+ // Check that construction still fails when 'skip_permissions_denied' is given
+ // because we tried to open a file and not a directory.
+ {
+ std::error_code ec;
+ RDI it(testFile, directory_options::skip_permission_denied, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == RDI{});
+ }
+}
+
+TEST_CASE(test_open_on_empty_directory_equals_end)
+{
+ scoped_test_env env;
+ const path testDir = env.make_env_path("dir1");
+ env.create_dir(testDir);
+
+ const RDI endIt;
+ {
+ std::error_code ec;
+ RDI it(testDir, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ RDI it(testDir);
+ TEST_CHECK(it == endIt);
+ }
+}
+
+TEST_CASE(test_open_on_directory_succeeds)
+{
+ const path testDir = StaticEnv::Dir;
+ std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
+ std::end( StaticEnv::DirIterationList));
+ const RDI endIt{};
+
+ {
+ std::error_code ec;
+ RDI it(testDir, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it != endIt);
+ TEST_CHECK(dir_contents.count(*it));
+ }
+ {
+ RDI it(testDir);
+ TEST_CHECK(it != endIt);
+ TEST_CHECK(dir_contents.count(*it));
+ }
+}
+
+TEST_CASE(test_open_on_file_fails)
+{
+ const path testFile = StaticEnv::File;
+ const RDI endIt{};
+ {
+ std::error_code ec;
+ RDI it(testFile, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ TEST_CHECK_THROW(filesystem_error, RDI(testFile));
+ }
+}
+
+TEST_CASE(test_options_post_conditions)
+{
+ const path goodDir = StaticEnv::Dir;
+ const path badDir = StaticEnv::DNE;
+
+ {
+ std::error_code ec;
+
+ RDI it1(goodDir, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it1.options() == directory_options::none);
+
+ RDI it2(badDir, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(it2 == RDI{});
+ }
+ {
+ std::error_code ec;
+ const directory_options opts = directory_options::skip_permission_denied;
+
+ RDI it1(goodDir, opts, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it1.options() == opts);
+
+ RDI it2(badDir, opts, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(it2 == RDI{});
+ }
+ {
+ RDI it(goodDir);
+ TEST_CHECK(it.options() == directory_options::none);
+ }
+ {
+ const directory_options opts = directory_options::follow_directory_symlink;
+ RDI it(goodDir, opts);
+ TEST_CHECK(it.options() == opts);
+ }
+}
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// int depth() const
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_depth_tests)
+
+TEST_CASE(test_depth)
+{
+ const path testDir = StaticEnv::Dir;
+ const path DirDepth1 = StaticEnv::Dir2;
+ const path DirDepth2 = StaticEnv::Dir3;
+ const recursive_directory_iterator endIt{};
+
+ std::error_code ec;
+ recursive_directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(it.depth() == 0);
+
+ bool seen_d1, seen_d2;
+ seen_d1 = seen_d2 = false;
+
+ while (it != endIt) {
+ const path entry = *it;
+ const path parent = entry.parent_path();
+ if (parent == testDir) {
+ TEST_CHECK(it.depth() == 0);
+ } else if (parent == DirDepth1) {
+ TEST_CHECK(it.depth() == 1);
+ seen_d1 = true;
+ } else if (parent == DirDepth2) {
+ TEST_CHECK(it.depth() == 2);
+ seen_d2 = true;
+ } else {
+ TEST_CHECK(!"Unexpected depth while iterating over static env");
+ }
+ ++it;
+ }
+ TEST_REQUIRE(seen_d1 && seen_d2);
+ TEST_CHECK(it == endIt);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// void disable_recursion_pending();
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_disable_recursion_pending_tests)
+
+// NOTE: The main semantics of disable_recursion_pending are tested
+// in the 'recursion_pending()' tests.
+TEST_CASE(basic_test)
+{
+ recursive_directory_iterator it(StaticEnv::Dir);
+ TEST_REQUIRE(it.recursion_pending() == true);
+ it.disable_recursion_pending();
+ TEST_CHECK(it.recursion_pending() == false);
+ it.disable_recursion_pending();
+ TEST_CHECK(it.recursion_pending() == false);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// recursive_directory_iterator& operator++();
+// recursive_directory_iterator& increment(error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_increment_tests)
+
+TEST_CASE(test_increment_signatures)
+{
+ using D = recursive_directory_iterator;
+ recursive_directory_iterator d; ((void)d);
+ std::error_code ec; ((void)ec);
+
+ ASSERT_SAME_TYPE(decltype(++d), recursive_directory_iterator&);
+ ASSERT_NOT_NOEXCEPT(++d);
+
+ ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&);
+ ASSERT_NOT_NOEXCEPT(d.increment(ec));
+}
+
+TEST_CASE(test_prefix_increment)
+{
+ const path testDir = StaticEnv::Dir;
+ const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
+ std::end( StaticEnv::RecDirIterationList));
+ const recursive_directory_iterator endIt{};
+
+ std::error_code ec;
+ recursive_directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ recursive_directory_iterator& it_ref = ++it;
+ TEST_CHECK(&it_ref == &it);
+ }
+
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(test_postfix_increment)
+{
+ const path testDir = StaticEnv::Dir;
+ const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
+ std::end( StaticEnv::RecDirIterationList));
+ const recursive_directory_iterator endIt{};
+
+ std::error_code ec;
+ recursive_directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ const path entry2 = *it++;
+ TEST_CHECK(entry2 == entry);
+ }
+ TEST_CHECK(it == endIt);
+}
+
+
+TEST_CASE(test_increment_method)
+{
+ const path testDir = StaticEnv::Dir;
+ const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
+ std::end( StaticEnv::RecDirIterationList));
+ const recursive_directory_iterator endIt{};
+
+ std::error_code ec;
+ recursive_directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ recursive_directory_iterator& it_ref = it.increment(ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(&it_ref == &it);
+ }
+
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(test_follow_symlinks)
+{
+ const path testDir = StaticEnv::Dir;
+ auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList;
+
+ const std::set<path> dir_contents(std::begin(IterList), std::end(IterList));
+ const recursive_directory_iterator endIt{};
+
+ std::error_code ec;
+ recursive_directory_iterator it(testDir,
+ directory_options::follow_directory_symlink, ec);
+ TEST_REQUIRE(!ec);
+
+ std::set<path> unseen_entries = dir_contents;
+ while (!unseen_entries.empty()) {
+ TEST_REQUIRE(it != endIt);
+ const path entry = *it;
+
+ TEST_REQUIRE(unseen_entries.erase(entry) == 1);
+ recursive_directory_iterator& it_ref = it.increment(ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(&it_ref == &it);
+ }
+ TEST_CHECK(it == endIt);
+}
+
+TEST_CASE(access_denied_on_recursion_test_case)
+{
+ using namespace fs;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_dir("dir1/dir2"),
+ env.create_file("dir1/dir2/file1"),
+ env.create_file("dir1/file2")
+ };
+ const path startDir = testFiles[0];
+ const path permDeniedDir = testFiles[1];
+ const path otherFile = testFiles[3];
+ auto SkipEPerm = directory_options::skip_permission_denied;
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir, perms::none);
+
+ const recursive_directory_iterator endIt;
+
+ // Test that recursion resulting in a "EACCESS" error is not ignored
+ // by default.
+ {
+ std::error_code ec = GetTestEC();
+ recursive_directory_iterator it(startDir, ec);
+ TEST_REQUIRE(ec != GetTestEC());
+ TEST_REQUIRE(!ec);
+ while (it != endIt && it->path() != permDeniedDir)
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == permDeniedDir);
+
+ it.increment(ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(it == endIt);
+ }
+ // Same as above but test operator++().
+ {
+ std::error_code ec = GetTestEC();
+ recursive_directory_iterator it(startDir, ec);
+ TEST_REQUIRE(!ec);
+ while (it != endIt && it->path() != permDeniedDir)
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == permDeniedDir);
+
+ TEST_REQUIRE_THROW(filesystem_error, ++it);
+ }
+ // Test that recursion resulting in a "EACCESS" error is ignored when the
+ // correct options are given to the constructor.
+ {
+ std::error_code ec = GetTestEC();
+ recursive_directory_iterator it(startDir, SkipEPerm, ec);
+ TEST_REQUIRE(!ec);
+ TEST_REQUIRE(it != endIt);
+
+ bool seenOtherFile = false;
+ if (*it == otherFile) {
+ ++it;
+ seenOtherFile = true;
+ TEST_REQUIRE (it != endIt);
+ }
+ TEST_REQUIRE(*it == permDeniedDir);
+
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_REQUIRE(!ec);
+
+ if (seenOtherFile) {
+ TEST_CHECK(it == endIt);
+ } else {
+ TEST_CHECK(it != endIt);
+ TEST_CHECK(*it == otherFile);
+ }
+ }
+ // Test that construction resulting in a "EACCESS" error is not ignored
+ // by default.
+ {
+ std::error_code ec;
+ recursive_directory_iterator it(permDeniedDir, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(it == endIt);
+ }
+ // Same as above but testing the throwing constructors
+ {
+ TEST_REQUIRE_THROW(filesystem_error,
+ recursive_directory_iterator(permDeniedDir));
+ }
+ // Test that construction resulting in a "EACCESS" error constructs the
+ // end iterator when the correct options are given.
+ {
+ std::error_code ec = GetTestEC();
+ recursive_directory_iterator it(permDeniedDir, SkipEPerm, ec);
+ TEST_REQUIRE(!ec);
+ TEST_REQUIRE(it == endIt);
+ }
+}
+
+// See llvm.org/PR35078
+TEST_CASE(test_PR35078)
+{
+ using namespace fs;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_dir("dir1/dir2"),
+ env.create_dir("dir1/dir2/dir3"),
+ env.create_file("dir1/file1"),
+ env.create_file("dir1/dir2/dir3/file2")
+ };
+ const path startDir = testFiles[0];
+ const path permDeniedDir = testFiles[1];
+ const path nestedDir = testFiles[2];
+ const path nestedFile = testFiles[3];
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir,
+ perms::group_exec|perms::owner_exec|perms::others_exec,
+ perm_options::remove);
+
+ const std::error_code eacess_ec =
+ std::make_error_code(std::errc::permission_denied);
+ std::error_code ec = GetTestEC();
+
+ const recursive_directory_iterator endIt;
+
+ auto SetupState = [&](bool AllowEAccess, bool& SeenFile3) {
+ SeenFile3 = false;
+ auto Opts = AllowEAccess ? directory_options::skip_permission_denied
+ : directory_options::none;
+ recursive_directory_iterator it(startDir, Opts, ec);
+ while (!ec && it != endIt && *it != nestedDir) {
+ if (*it == nestedFile)
+ SeenFile3 = true;
+ it.increment(ec);
+ }
+ return it;
+ };
+
+ {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(false, SeenNestedFile);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == nestedDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec == eacess_ec);
+ TEST_CHECK(it == endIt);
+ }
+ {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(true, SeenNestedFile);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == nestedDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_CHECK(!ec);
+ if (SeenNestedFile) {
+ TEST_CHECK(it == endIt);
+ } else {
+ TEST_REQUIRE(it != endIt);
+ TEST_CHECK(*it == nestedFile);
+ }
+ }
+ {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(false, SeenNestedFile);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == nestedDir);
+
+ ExceptionChecker Checker(std::errc::permission_denied,
+ "recursive_directory_iterator::operator++()",
+ format_string("attempting recursion into \"%s\"",
+ nestedDir.native()));
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ++it);
+ }
+}
+
+
+// See llvm.org/PR35078
+TEST_CASE(test_PR35078_with_symlink)
+{
+ using namespace fs;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_file("dir1/file1"),
+ env.create_dir("sym_dir"),
+ env.create_dir("sym_dir/nested_sym_dir"),
+ env.create_symlink("sym_dir/nested_sym_dir", "dir1/dir2"),
+ env.create_dir("sym_dir/dir1"),
+ env.create_dir("sym_dir/dir1/dir2"),
+
+ };
+ // const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
+ const path startDir = testFiles[0];
+ const path nestedFile = testFiles[1];
+ const path permDeniedDir = testFiles[2];
+ const path symDir = testFiles[4];
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir,
+ perms::group_exec|perms::owner_exec|perms::others_exec,
+ perm_options::remove);
+
+ const std::error_code eacess_ec =
+ std::make_error_code(std::errc::permission_denied);
+ std::error_code ec = GetTestEC();
+
+ const recursive_directory_iterator endIt;
+
+ auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenFile3) {
+ SeenFile3 = false;
+ auto Opts = AllowEAccess ? directory_options::skip_permission_denied
+ : directory_options::none;
+ if (FollowSym)
+ Opts |= directory_options::follow_directory_symlink;
+ recursive_directory_iterator it(startDir, Opts, ec);
+ while (!ec && it != endIt && *it != symDir) {
+ if (*it == nestedFile)
+ SeenFile3 = true;
+ it.increment(ec);
+ }
+ return it;
+ };
+
+ struct {
+ bool SkipPermDenied;
+ bool FollowSymlinks;
+ bool ExpectSuccess;
+ } TestCases[] = {
+ // Passing cases
+ {false, false, true}, {true, true, true}, {true, false, true},
+ // Failing cases
+ {false, true, false}
+ };
+ for (auto TC : TestCases) {
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
+ TC.FollowSymlinks,
+ SeenNestedFile);
+ TEST_REQUIRE(!ec);
+ TEST_REQUIRE(it != endIt);
+ TEST_REQUIRE(*it == symDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ if (TC.ExpectSuccess) {
+ TEST_CHECK(!ec);
+ if (SeenNestedFile) {
+ TEST_CHECK(it == endIt);
+ } else {
+ TEST_REQUIRE(it != endIt);
+ TEST_CHECK(*it == nestedFile);
+ }
+ } else {
+ TEST_CHECK(ec);
+ TEST_CHECK(ec == eacess_ec);
+ TEST_CHECK(it == endIt);
+ }
+ }
+}
+
+
+// See llvm.org/PR35078
+TEST_CASE(test_PR35078_with_symlink_file)
+{
+ using namespace fs;
+ scoped_test_env env;
+ const path testFiles[] = {
+ env.create_dir("dir1"),
+ env.create_dir("dir1/dir2"),
+ env.create_file("dir1/file2"),
+ env.create_dir("sym_dir"),
+ env.create_dir("sym_dir/sdir1"),
+ env.create_file("sym_dir/sdir1/sfile1"),
+ env.create_symlink("sym_dir/sdir1/sfile1", "dir1/dir2/file1")
+ };
+ const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
+ const path startDir = testFiles[0];
+ const path nestedDir = testFiles[1];
+ const path nestedFile = testFiles[2];
+ const path permDeniedDir = testFiles[3];
+ const path symFile = testFiles[TestFilesSize - 1];
+
+ // Change the permissions so we can no longer iterate
+ permissions(permDeniedDir,
+ perms::group_exec|perms::owner_exec|perms::others_exec,
+ perm_options::remove);
+
+ const std::error_code eacess_ec =
+ std::make_error_code(std::errc::permission_denied);
+ std::error_code ec = GetTestEC();
+
+ const recursive_directory_iterator EndIt;
+
+ auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenNestedFile) {
+ SeenNestedFile = false;
+ auto Opts = AllowEAccess ? directory_options::skip_permission_denied
+ : directory_options::none;
+ if (FollowSym)
+ Opts |= directory_options::follow_directory_symlink;
+ recursive_directory_iterator it(startDir, Opts, ec);
+ while (!ec && it != EndIt && *it != nestedDir) {
+ if (*it == nestedFile)
+ SeenNestedFile = true;
+ it.increment(ec);
+ }
+ return it;
+ };
+
+ struct {
+ bool SkipPermDenied;
+ bool FollowSymlinks;
+ bool ExpectSuccess;
+ } TestCases[] = {
+ // Passing cases
+ {false, false, true}, {true, true, true}, {true, false, true},
+ // Failing cases
+ {false, true, false}
+ };
+ for (auto TC : TestCases){
+ bool SeenNestedFile = false;
+ recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
+ TC.FollowSymlinks,
+ SeenNestedFile);
+ TEST_REQUIRE(!ec);
+ TEST_REQUIRE(it != EndIt);
+ TEST_REQUIRE(*it == nestedDir);
+ ec = GetTestEC();
+ it.increment(ec);
+ TEST_REQUIRE(it != EndIt);
+ TEST_CHECK(!ec);
+ TEST_CHECK(*it == symFile);
+ ec = GetTestEC();
+ it.increment(ec);
+ if (TC.ExpectSuccess) {
+ if (!SeenNestedFile) {
+ TEST_CHECK(!ec);
+ TEST_REQUIRE(it != EndIt);
+ TEST_CHECK(*it == nestedFile);
+ ec = GetTestEC();
+ it.increment(ec);
+ }
+ TEST_CHECK(!ec);
+ TEST_CHECK(it == EndIt);
+ } else {
+ TEST_CHECK(ec);
+ TEST_CHECK(ec == eacess_ec);
+ TEST_CHECK(it == EndIt);
+ }
+ }
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// recursive_directory_iterator(recursive_directory_iterator&&) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_move_construct_tests)
+
+TEST_CASE(test_constructor_signature)
+{
+ using D = recursive_directory_iterator;
+ static_assert(std::is_nothrow_move_constructible<D>::value, "");
+}
+
+TEST_CASE(test_move_end_iterator)
+{
+ const recursive_directory_iterator endIt;
+ recursive_directory_iterator endIt2{};
+
+ recursive_directory_iterator it(std::move(endIt2));
+ TEST_CHECK(it == endIt);
+ TEST_CHECK(endIt2 == endIt);
+}
+
+TEST_CASE(test_move_valid_iterator)
+{
+ const path testDir = StaticEnv::Dir;
+ const recursive_directory_iterator endIt{};
+
+ // build 'it' up with "interesting" non-default state so we can test
+ // that it gets copied. We want to get 'it' into a state such that:
+ // it.options() != directory_options::none
+ // it.depth() != 0
+ // it.recursion_pending() != true
+ const directory_options opts = directory_options::skip_permission_denied;
+ recursive_directory_iterator it(testDir, opts);
+ TEST_REQUIRE(it != endIt);
+ while (it.depth() == 0) {
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ }
+ it.disable_recursion_pending();
+ TEST_CHECK(it.options() == opts);
+ TEST_CHECK(it.depth() == 1);
+ TEST_CHECK(it.recursion_pending() == false);
+ const path entry = *it;
+
+ // OPERATION UNDER TEST //
+ const recursive_directory_iterator it2(std::move(it));
+ // ------------------- //
+
+ TEST_REQUIRE(it2 != endIt);
+ TEST_CHECK(*it2 == entry);
+ TEST_CHECK(it2.depth() == 1);
+ TEST_CHECK(it2.recursion_pending() == false);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// recursive_directory_iterator& operator=(recursive_directory_iterator const&);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+// The filesystem specification explicitly allows for self-move on
+// the directory iterators. Turn off this warning so we can test it.
+#if defined(__clang__)
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_move_assign_tests)
+
+recursive_directory_iterator createInterestingIterator()
+ // Create an "interesting" iterator where all fields are
+ // in a non-default state. The returned 'it' is in a
+ // state such that:
+ // it.options() == directory_options::skip_permission_denied
+ // it.depth() == 1
+ // it.recursion_pending() == true
+{
+ const path testDir = StaticEnv::Dir;
+ const recursive_directory_iterator endIt;
+ recursive_directory_iterator it(testDir,
+ directory_options::skip_permission_denied);
+ TEST_ASSERT(it != endIt);
+ while (it.depth() != 1) {
+ ++it;
+ TEST_ASSERT(it != endIt);
+ }
+ TEST_ASSERT(it.depth() == 1);
+ it.disable_recursion_pending();
+ return it;
+}
+
+recursive_directory_iterator createDifferentInterestingIterator()
+ // Create an "interesting" iterator where all fields are
+ // in a non-default state. The returned 'it' is in a
+ // state such that:
+ // it.options() == directory_options::follow_directory_symlink
+ // it.depth() == 2
+ // it.recursion_pending() == false
+{
+ const path testDir = StaticEnv::Dir;
+ const recursive_directory_iterator endIt;
+ recursive_directory_iterator it(testDir,
+ directory_options::follow_directory_symlink);
+ TEST_ASSERT(it != endIt);
+ while (it.depth() != 2) {
+ ++it;
+ TEST_ASSERT(it != endIt);
+ }
+ TEST_ASSERT(it.depth() == 2);
+ return it;
+}
+
+
+TEST_CASE(test_assignment_signature)
+{
+ using D = recursive_directory_iterator;
+ static_assert(std::is_nothrow_move_assignable<D>::value, "");
+}
+
+
+TEST_CASE(test_move_to_end_iterator)
+{
+ const recursive_directory_iterator endIt;
+
+ recursive_directory_iterator from = createInterestingIterator();
+ const recursive_directory_iterator from_copy(from);
+ const path entry = *from;
+
+ recursive_directory_iterator to;
+ to = std::move(from);
+ TEST_REQUIRE(to != endIt);
+ TEST_CHECK(*to == entry);
+ TEST_CHECK(to.options() == from_copy.options());
+ TEST_CHECK(to.depth() == from_copy.depth());
+ TEST_CHECK(to.recursion_pending() == from_copy.recursion_pending());
+ TEST_CHECK(from == endIt || from == to);
+}
+
+
+TEST_CASE(test_move_from_end_iterator)
+{
+ recursive_directory_iterator from;
+ recursive_directory_iterator to = createInterestingIterator();
+
+ to = std::move(from);
+ TEST_REQUIRE(to == from);
+ TEST_CHECK(to == recursive_directory_iterator{});
+}
+
+TEST_CASE(test_move_valid_iterator)
+{
+ const recursive_directory_iterator endIt;
+
+ recursive_directory_iterator it = createInterestingIterator();
+ const recursive_directory_iterator it_copy(it);
+ const path entry = *it;
+
+ recursive_directory_iterator it2 = createDifferentInterestingIterator();
+ const recursive_directory_iterator it2_copy(it2);
+ TEST_REQUIRE(it2 != it);
+ TEST_CHECK(it2.options() != it.options());
+ TEST_CHECK(it2.depth() != it.depth());
+ TEST_CHECK(it2.recursion_pending() != it.recursion_pending());
+ TEST_CHECK(*it2 != entry);
+
+ it2 = std::move(it);
+ TEST_REQUIRE(it2 != it2_copy && it2 != endIt);
+ TEST_CHECK(it2.options() == it_copy.options());
+ TEST_CHECK(it2.depth() == it_copy.depth());
+ TEST_CHECK(it2.recursion_pending() == it_copy.recursion_pending());
+ TEST_CHECK(*it2 == entry);
+ TEST_CHECK(it == endIt || it == it2);
+}
+
+TEST_CASE(test_returns_reference_to_self)
+{
+ recursive_directory_iterator it;
+ recursive_directory_iterator it2;
+ recursive_directory_iterator& ref = (it2 = std::move(it));
+ TEST_CHECK(&ref == &it2);
+}
+
+TEST_CASE(test_self_move)
+{
+ // Create two non-equal iterators that have exactly the same state.
+ recursive_directory_iterator it = createInterestingIterator();
+ recursive_directory_iterator it2 = createInterestingIterator();
+ TEST_CHECK(it != it2);
+ TEST_CHECK(it2.options() == it.options());
+ TEST_CHECK(it2.depth() == it.depth());
+ TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
+ TEST_CHECK(*it2 == *it);
+
+ it = std::move(it);
+ TEST_CHECK(it2.options() == it.options());
+ TEST_CHECK(it2.depth() == it.depth());
+ TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
+ TEST_CHECK(*it2 == *it);
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// void pop();
+// void pop(error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_pop_tests)
+
+TEST_CASE(signature_tests)
+{
+ recursive_directory_iterator it{}; ((void)it);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(it.pop());
+ ASSERT_NOT_NOEXCEPT(it.pop(ec)); // may require allocation or other things
+}
+
+// NOTE: Since the order of iteration is unspecified we use a list of
+// seen files at each depth to determine the new depth after a 'pop()' operation.
+TEST_CASE(test_depth)
+{
+ const recursive_directory_iterator endIt{};
+
+ auto& DE0 = StaticEnv::DirIterationList;
+ std::set<path> notSeenDepth0(std::begin(DE0), std::end(DE0));
+
+ auto& DE1 = StaticEnv::DirIterationListDepth1;
+ std::set<path> notSeenDepth1(std::begin(DE1), std::end(DE1));
+
+ std::error_code ec;
+ recursive_directory_iterator it(StaticEnv::Dir, ec);
+ TEST_REQUIRE(it != endIt);
+ TEST_CHECK(it.depth() == 0);
+
+ while (it.depth() != 2) {
+ if (it.depth() == 0)
+ notSeenDepth0.erase(it->path());
+ else
+ notSeenDepth1.erase(it->path());
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ }
+
+ while (true) {
+ auto set_ec = std::make_error_code(std::errc::address_in_use);
+ it.pop(set_ec);
+ TEST_REQUIRE(!set_ec);
+
+ if (it == endIt) {
+ // We must have seen every entry at depth 0 and 1.
+ TEST_REQUIRE(notSeenDepth0.empty() && notSeenDepth1.empty());
+ break;
+ }
+ else if (it.depth() == 1) {
+ // If we popped to depth 1 then there must be unseen entries
+ // at this level.
+ TEST_REQUIRE(!notSeenDepth1.empty());
+ TEST_CHECK(notSeenDepth1.count(it->path()));
+ notSeenDepth1.clear();
+ }
+ else if (it.depth() == 0) {
+ // If we popped to depth 0 there must be unseen entries at this
+ // level. There should also be no unseen entries at depth 1.
+ TEST_REQUIRE(!notSeenDepth0.empty());
+ TEST_REQUIRE(notSeenDepth1.empty());
+ TEST_CHECK(notSeenDepth0.count(it->path()));
+ notSeenDepth0.clear();
+ }
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// bool recursion_pending() const;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_recursion_pending_tests)
+
+TEST_CASE(initial_value_test)
+{
+ recursive_directory_iterator it(StaticEnv::Dir);
+ TEST_REQUIRE(it.recursion_pending() == true);
+}
+
+TEST_CASE(value_after_copy_construction_and_assignment_test)
+{
+ recursive_directory_iterator rec_pending_it(StaticEnv::Dir);
+ recursive_directory_iterator no_rec_pending_it(StaticEnv::Dir);
+ no_rec_pending_it.disable_recursion_pending();
+
+ { // copy construction
+ recursive_directory_iterator it(rec_pending_it);
+ TEST_CHECK(it.recursion_pending() == true);
+ it.disable_recursion_pending();
+ TEST_REQUIRE(rec_pending_it.recursion_pending() == true);
+
+ recursive_directory_iterator it2(no_rec_pending_it);
+ TEST_CHECK(it2.recursion_pending() == false);
+ }
+ { // copy assignment
+ recursive_directory_iterator it(StaticEnv::Dir);
+ it.disable_recursion_pending();
+ it = rec_pending_it;
+ TEST_CHECK(it.recursion_pending() == true);
+ it.disable_recursion_pending();
+ TEST_REQUIRE(rec_pending_it.recursion_pending() == true);
+
+ recursive_directory_iterator it2(StaticEnv::Dir);
+ it2 = no_rec_pending_it;
+ TEST_CHECK(it2.recursion_pending() == false);
+ }
+ TEST_CHECK(rec_pending_it.recursion_pending() == true);
+ TEST_CHECK(no_rec_pending_it.recursion_pending() == false);
+}
+
+
+TEST_CASE(value_after_move_construction_and_assignment_test)
+{
+ recursive_directory_iterator rec_pending_it(StaticEnv::Dir);
+ recursive_directory_iterator no_rec_pending_it(StaticEnv::Dir);
+ no_rec_pending_it.disable_recursion_pending();
+
+ { // move construction
+ recursive_directory_iterator it_cp(rec_pending_it);
+ recursive_directory_iterator it(std::move(it_cp));
+ TEST_CHECK(it.recursion_pending() == true);
+
+ recursive_directory_iterator it_cp2(no_rec_pending_it);
+ recursive_directory_iterator it2(std::move(it_cp2));
+ TEST_CHECK(it2.recursion_pending() == false);
+ }
+ { // copy assignment
+ recursive_directory_iterator it(StaticEnv::Dir);
+ it.disable_recursion_pending();
+ recursive_directory_iterator it_cp(rec_pending_it);
+ it = std::move(it_cp);
+ TEST_CHECK(it.recursion_pending() == true);
+
+ recursive_directory_iterator it2(StaticEnv::Dir);
+ recursive_directory_iterator it_cp2(no_rec_pending_it);
+ it2 = std::move(it_cp2);
+ TEST_CHECK(it2.recursion_pending() == false);
+ }
+ TEST_CHECK(rec_pending_it.recursion_pending() == true);
+ TEST_CHECK(no_rec_pending_it.recursion_pending() == false);
+}
+
+TEST_CASE(increment_resets_value)
+{
+ const recursive_directory_iterator endIt;
+ {
+ recursive_directory_iterator it(StaticEnv::Dir);
+ it.disable_recursion_pending();
+ TEST_CHECK(it.recursion_pending() == false);
+ ++it;
+ TEST_CHECK(it.recursion_pending() == true);
+ TEST_CHECK(it.depth() == 0);
+ }
+ {
+ recursive_directory_iterator it(StaticEnv::Dir);
+ it.disable_recursion_pending();
+ TEST_CHECK(it.recursion_pending() == false);
+ it++;
+ TEST_CHECK(it.recursion_pending() == true);
+ TEST_CHECK(it.depth() == 0);
+ }
+ {
+ recursive_directory_iterator it(StaticEnv::Dir);
+ it.disable_recursion_pending();
+ TEST_CHECK(it.recursion_pending() == false);
+ std::error_code ec;
+ it.increment(ec);
+ TEST_CHECK(it.recursion_pending() == true);
+ TEST_CHECK(it.depth() == 0);
+ }
+}
+
+TEST_CASE(pop_does_not_reset_value)
+{
+ const recursive_directory_iterator endIt;
+
+ auto& DE0 = StaticEnv::DirIterationList;
+ std::set<path> notSeenDepth0(std::begin(DE0), std::end(DE0));
+
+ recursive_directory_iterator it(StaticEnv::Dir);
+ TEST_REQUIRE(it != endIt);
+
+ while (it.depth() == 0) {
+ notSeenDepth0.erase(it->path());
+ ++it;
+ TEST_REQUIRE(it != endIt);
+ }
+ TEST_REQUIRE(it.depth() == 1);
+ it.disable_recursion_pending();
+ it.pop();
+ // Since the order of iteration is unspecified the pop() could result
+ // in the end iterator. When this is the case it is undefined behavior
+ // to call recursion_pending().
+ if (it == endIt) {
+ TEST_CHECK(notSeenDepth0.empty());
+#if defined(_LIBCPP_VERSION)
+ TEST_CHECK(it.recursion_pending() == false);
+#endif
+ } else {
+ TEST_CHECK(! notSeenDepth0.empty());
+ TEST_CHECK(it.recursion_pending() == false);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class recursive_directory_iterator
+
+// recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept;
+// recursive_directory_iterator end(recursive_directory_iterator iter) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <set>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+#include <iostream>
+
+using namespace fs;
+
+TEST_SUITE(recursive_directory_iterator_begin_end_tests)
+
+TEST_CASE(test_function_signatures)
+{
+ using D = recursive_directory_iterator;
+ recursive_directory_iterator d; ((void)d);
+
+ ASSERT_SAME_TYPE(decltype(begin(d)), recursive_directory_iterator);
+ ASSERT_NOEXCEPT(begin(std::move(d)));
+
+ ASSERT_SAME_TYPE(decltype(end(d)), recursive_directory_iterator);
+ ASSERT_NOEXCEPT(end(std::move(d)));
+}
+
+TEST_CASE(test_ranged_for_loop)
+{
+ const path testDir = StaticEnv::Dir;
+ std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
+ std::end( StaticEnv::RecDirIterationList));
+
+ std::error_code ec;
+ recursive_directory_iterator it(testDir, ec);
+ TEST_REQUIRE(!ec);
+
+ for (auto& elem : it) {
+ TEST_CHECK(dir_contents.erase(elem) == 1);
+ }
+ TEST_CHECK(dir_contents.empty());
+}
+
+TEST_SUITE_END()
--- /dev/null
+#ifndef TEST_BITMASK_TYPE_HPP
+#define TEST_BITMASK_TYPE_HPP
+
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+template <class EnumType, EnumType Val1, EnumType Val2,
+ class UT = typename std::underlying_type<EnumType>::type,
+ UT UVal1 = static_cast<UT>(Val1),
+ UT UVal2 = static_cast<UT>(Val2),
+ UT UZero = static_cast<UT>(0),
+ EnumType Zero = static_cast<EnumType>(0)
+ >
+struct check_bitmask_type {
+
+ static constexpr UT dcast(EnumType e) { return static_cast<UT>(e); }
+ static constexpr UT unpromote(decltype((~UZero)) promoted) { return static_cast<UT>(promoted); }
+ // We need two values that are non-zero and share at least one bit.
+ static_assert(Val1 != Zero && Val2 != Zero, "");
+ static_assert(Val1 != Val2, "");
+ static_assert((UVal1 & UVal2) == 0, "");
+
+
+ static bool check()
+ {
+ {
+ EnumType ValRef = Val1;
+ ASSERT_SAME_TYPE(EnumType, decltype(Val1 & Val2));
+ ASSERT_SAME_TYPE(EnumType, decltype(Val1 | Val2));
+ ASSERT_SAME_TYPE(EnumType, decltype(Val1 ^ Val2));
+ ASSERT_SAME_TYPE(EnumType, decltype((~Val1)));
+ ASSERT_SAME_TYPE(EnumType&, decltype(ValRef &= Val2));
+ ASSERT_SAME_TYPE(EnumType&, decltype(ValRef |= Val2));
+ ASSERT_SAME_TYPE(EnumType&, decltype(ValRef ^= Val2));
+ }
+
+ static_assert((Val1 & Zero) == Zero, "");
+ static_assert((Val1 & Val1) == Val1, "");
+ static_assert(dcast(Val1 & Val2) == (UVal1 & UVal2), "");
+
+ static_assert((Val1 | Zero) == Val1, "");
+ static_assert(dcast(Val1 | Val2) == (UVal1 | UVal2), "");
+
+ static_assert((Val1 ^ Zero) == Val1, "");
+ static_assert(dcast(Val1 ^ Val2) == (UVal1 ^ UVal2), "");
+
+ static_assert(dcast(~Zero) == unpromote(~UZero), "");
+ static_assert(dcast(~Val1) == unpromote(~UVal1), "");
+
+ {
+ EnumType e = Val1;
+ EnumType& eref = (e &= Val2);
+ assert(&eref == &e);
+ assert(dcast(eref) == (UVal1 & UVal2));
+ }
+ {
+ EnumType e = Val1;
+ EnumType& eref = (e |= Val2);
+ assert(&eref == &e);
+ assert(dcast(eref) == (UVal1 | UVal2));
+ }
+ {
+ EnumType e = Val1;
+ EnumType& eref = (e ^= Val2);
+ assert(&eref == &e);
+ assert(dcast(eref) == (UVal1 ^ UVal2));
+ }
+ return true;
+ }
+};
+
+#endif // TEST_BITMASK_TYPE
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// enum class copy_options;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "check_bitmask_types.hpp"
+#include "test_macros.h"
+
+
+constexpr fs::copy_options ME(int val) { return static_cast<fs::copy_options>(val); }
+
+int main() {
+ typedef fs::copy_options E;
+ static_assert(std::is_enum<E>::value, "");
+
+ // Check that E is a scoped enum by checking for conversions.
+ typedef std::underlying_type<E>::type UT;
+ static_assert(!std::is_convertible<E, UT>::value, "");
+
+ static_assert(std::is_same<UT, unsigned short>::value, ""); // Implementation detail
+
+ typedef check_bitmask_type<E, E::skip_existing, E::update_existing> BitmaskTester;
+ assert(BitmaskTester::check());
+
+ static_assert(
+ E::none == ME(0),
+ "Expected enumeration values do not match");
+ // Option group for copy_file
+ static_assert(
+ E::skip_existing == ME(1) &&
+ E::overwrite_existing == ME(2) &&
+ E::update_existing == ME(4),
+ "Expected enumeration values do not match");
+ // Option group for copy on directories
+ static_assert(
+ E::recursive == ME(8),
+ "Expected enumeration values do not match");
+ // Option group for copy on symlinks
+ static_assert(
+ E::copy_symlinks == ME(16) &&
+ E::skip_symlinks == ME(32),
+ "Expected enumeration values do not match");
+ // Option group for changing form of copy
+ static_assert(
+ E::directories_only == ME(64) &&
+ E::create_symlinks == ME(128) &&
+ E::create_hard_links == ME(256),
+ "Expected enumeration values do not match");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// enum class directory_options;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+#include <sys/stat.h>
+
+#include "test_macros.h"
+#include "check_bitmask_types.hpp"
+
+
+constexpr fs::directory_options ME(int val) { return static_cast<fs::directory_options>(val); }
+
+int main() {
+ typedef fs::directory_options E;
+ static_assert(std::is_enum<E>::value, "");
+
+ // Check that E is a scoped enum by checking for conversions.
+ typedef std::underlying_type<E>::type UT;
+ static_assert(!std::is_convertible<E, UT>::value, "");
+ static_assert(std::is_same<UT, unsigned char>::value, "");
+
+ typedef check_bitmask_type<E, E::follow_directory_symlink, E::skip_permission_denied> BitmaskTester;
+ assert(BitmaskTester::check());
+
+ static_assert(
+ E::none == ME(0) &&
+ E::follow_directory_symlink == ME(1) &&
+ E::skip_permission_denied == ME(2),
+ "Expected enumeration values do not match");
+
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// enum class file_type;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+
+constexpr fs::file_type ME(int val) { return static_cast<fs::file_type>(val); }
+
+int main() {
+ typedef fs::file_type E;
+ static_assert(std::is_enum<E>::value, "");
+
+ // Check that E is a scoped enum by checking for conversions.
+ typedef std::underlying_type<E>::type UT;
+ static_assert(!std::is_convertible<E, UT>::value, "");
+
+ static_assert(std::is_same<UT, signed char>::value, ""); // Implementation detail
+
+ static_assert(
+ E::none == ME(0) &&
+ E::not_found == ME(-1) &&
+ E::regular == ME(1) &&
+ E::directory == ME(2) &&
+ E::symlink == ME(3) &&
+ E::block == ME(4) &&
+ E::character == ME(5) &&
+ E::fifo == ME(6) &&
+ E::socket == ME(7) &&
+ E::unknown == ME(8),
+ "Expected enumeration values do not match");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// class path;
+// enum class format;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main() {
+ typedef fs::path::format E;
+ static_assert(std::is_enum<E>::value, "");
+
+ // Check that E is a scoped enum by checking for conversions.
+ typedef std::underlying_type<E>::type UT;
+ static_assert(!std::is_convertible<E, UT>::value, "");
+
+ LIBCPP_ONLY(static_assert(std::is_same<UT, unsigned char>::value, "")); // Implementation detail
+
+ static_assert(
+ E::auto_format != E::native_format &&
+ E::auto_format != E::generic_format &&
+ E::native_format != E::generic_format,
+ "Expected enumeration values are not unique");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// enum class perm_options;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+#include <sys/stat.h>
+
+#include "test_macros.h"
+#include "check_bitmask_types.hpp"
+
+
+constexpr fs::perm_options ME(int val) {
+ return static_cast<fs::perm_options>(val);
+}
+
+int main() {
+ typedef fs::perm_options E;
+ static_assert(std::is_enum<E>::value, "");
+
+ // Check that E is a scoped enum by checking for conversions.
+ typedef std::underlying_type<E>::type UT;
+ static_assert(!std::is_convertible<E, UT>::value, "");
+
+ static_assert(std::is_same<UT, unsigned char >::value, ""); // Implementation detail
+
+ typedef check_bitmask_type<E, E::replace, E::nofollow> BitmaskTester;
+ assert(BitmaskTester::check());
+
+ static_assert(
+ E::replace == ME(1) &&
+ E::add == ME(2) &&
+ E::remove == ME(4) &&
+ E::nofollow == ME(8),
+ "Expected enumeration values do not match");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// enum class perms;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+#include <sys/stat.h>
+
+#include "test_macros.h"
+#include "check_bitmask_types.hpp"
+
+
+constexpr fs::perms ME(int val) { return static_cast<fs::perms>(val); }
+
+int main() {
+ typedef fs::perms E;
+ static_assert(std::is_enum<E>::value, "");
+
+ // Check that E is a scoped enum by checking for conversions.
+ typedef std::underlying_type<E>::type UT;
+ static_assert(!std::is_convertible<E, UT>::value, "");
+
+ static_assert(std::is_same<UT, unsigned >::value, ""); // Implementation detail
+
+ typedef check_bitmask_type<E, E::group_all, E::owner_all> BitmaskTester;
+ assert(BitmaskTester::check());
+
+ static_assert(
+ E::none == ME(0) &&
+
+ E::owner_read == ME(0400) &&
+ E::owner_write == ME(0200) &&
+ E::owner_exec == ME(0100) &&
+ E::owner_all == ME(0700) &&
+
+ E::group_read == ME(040) &&
+ E::group_write == ME(020) &&
+ E::group_exec == ME(010) &&
+ E::group_all == ME(070) &&
+
+ E::others_read == ME(04) &&
+ E::others_write == ME(02) &&
+ E::others_exec == ME(01) &&
+ E::others_all == ME(07) &&
+ E::all == ME(0777) &&
+ E::set_uid == ME(04000) &&
+ E::set_gid == ME(02000) &&
+ E::sticky_bit == ME(01000) &&
+ E::mask == ME(07777) &&
+ E::unknown == ME(0xFFFF),
+ "Expected enumeration values do not match");
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int main()
+{
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// typedef TrivialClock file_time_type;
+
+#include "filesystem_include.hpp"
+#include <chrono>
+#include <type_traits>
+
+#include "test_macros.h"
+
+// system_clock is used because it meets the requirements of TrivialClock,
+// and the resolution and range of system_clock should match the operating
+// system's file time type.
+
+void test_trivial_clock() {
+ using namespace fs;
+ using Clock = file_time_type::clock;
+ ASSERT_NOEXCEPT(Clock::now());
+ ASSERT_SAME_TYPE(decltype(Clock::now()), file_time_type);
+ ASSERT_SAME_TYPE(Clock::time_point, file_time_type);
+ volatile auto* odr_use = &Clock::is_steady;
+ ((void)odr_use);
+}
+
+void test_time_point_resolution_and_range() {
+ using namespace fs;
+ using Dur = file_time_type::duration;
+ using Period = Dur::period;
+ ASSERT_SAME_TYPE(Period, std::nano);
+}
+
+int main() {
+ test_trivial_clock();
+ test_time_point_resolution_and_range();
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path absolute(const path& p, const path& base=current_path());
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_absolute_path_test_suite)
+
+TEST_CASE(absolute_signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec;
+ ASSERT_NOT_NOEXCEPT(absolute(p));
+ ASSERT_NOT_NOEXCEPT(absolute(p, ec));
+}
+
+
+TEST_CASE(basic_test)
+{
+ const fs::path cwd = fs::current_path();
+ const struct {
+ std::string input;
+ std::string expect;
+ } TestCases [] = {
+ {"", cwd / ""},
+ {"foo", cwd / "foo"},
+ {"foo/", cwd / "foo/"},
+ {"/already_absolute", "/already_absolute"}
+ };
+ for (auto& TC : TestCases) {
+ std::error_code ec = GetTestEC();
+ const path ret = absolute(TC.input, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ret.is_absolute());
+ TEST_CHECK(PathEq(ret, TC.expect));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path canonical(const path& p);
+// path canonical(const path& p, error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+struct CWDGuard {
+ path OldCWD;
+ CWDGuard() : OldCWD(fs::current_path()) { }
+ ~CWDGuard() { fs::current_path(OldCWD); }
+
+ CWDGuard(CWDGuard const&) = delete;
+ CWDGuard& operator=(CWDGuard const&) = delete;
+};
+
+TEST_SUITE(filesystem_canonical_path_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(canonical(p));
+ ASSERT_NOT_NOEXCEPT(canonical(p, ec));
+}
+
+// There are 4 cases is the proposal for absolute path.
+// Each scope tests one of the cases.
+TEST_CASE(test_canonical)
+{
+ CWDGuard guard;
+ // has_root_name() && has_root_directory()
+ const path Root = StaticEnv::Root;
+ const path RootName = Root.filename();
+ const path DirName = StaticEnv::Dir.filename();
+ const path SymlinkName = StaticEnv::SymlinkToFile.filename();
+ struct TestCase {
+ path p;
+ path expect;
+ path base;
+ TestCase(path p1, path e, path b = StaticEnv::Root)
+ : p(p1), expect(e), base(b) {}
+ };
+ const TestCase testCases[] = {
+ { ".", Root, Root},
+ { DirName / ".." / "." / DirName, StaticEnv::Dir, Root},
+ { StaticEnv::Dir2 / "..", StaticEnv::Dir },
+ { StaticEnv::Dir3 / "../..", StaticEnv::Dir },
+ { StaticEnv::Dir / ".", StaticEnv::Dir },
+ { Root / "." / DirName / ".." / DirName, StaticEnv::Dir},
+ { path("..") / "." / RootName / DirName / ".." / DirName, StaticEnv::Dir, Root},
+ { StaticEnv::SymlinkToFile, StaticEnv::File },
+ { SymlinkName, StaticEnv::File, StaticEnv::Root}
+ };
+ for (auto& TC : testCases) {
+ std::error_code ec = GetTestEC();
+ fs::current_path(TC.base);
+ const path ret = canonical(TC.p, ec);
+ TEST_REQUIRE(!ec);
+ const path ret2 = canonical(TC.p);
+ TEST_CHECK(PathEq(ret, TC.expect));
+ TEST_CHECK(PathEq(ret, ret2));
+ TEST_CHECK(ret.is_absolute());
+ }
+}
+
+TEST_CASE(test_dne_path)
+{
+ std::error_code ec = GetTestEC();
+ {
+ const path ret = canonical(StaticEnv::DNE, ec);
+ TEST_CHECK(ec != GetTestEC());
+ TEST_REQUIRE(ec);
+ TEST_CHECK(ret == path{});
+ }
+ {
+ TEST_CHECK_THROW(filesystem_error, canonical(StaticEnv::DNE));
+ }
+}
+
+TEST_CASE(test_exception_contains_paths)
+{
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ CWDGuard guard;
+ const path p = "blabla/dne";
+ try {
+ canonical(p);
+ TEST_REQUIRE(false);
+ } catch (filesystem_error const& err) {
+ TEST_CHECK(err.path1() == p);
+ // libc++ provides the current path as the second path in the exception
+ LIBCPP_ONLY(TEST_CHECK(err.path2() == current_path()));
+ }
+ fs::current_path(StaticEnv::Dir);
+ try {
+ canonical(p);
+ TEST_REQUIRE(false);
+ } catch (filesystem_error const& err) {
+ TEST_CHECK(err.path1() == p);
+ LIBCPP_ONLY(TEST_CHECK(err.path2() == StaticEnv::Dir));
+ }
+#endif
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void copy(const path& from, const path& to);
+// void copy(const path& from, const path& to, error_code& ec);
+// void copy(const path& from, const path& to, copy_options options);
+// void copy(const path& from, const path& to, copy_options options,
+// error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cstddef>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+using CO = fs::copy_options;
+
+TEST_SUITE(filesystem_copy_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ const copy_options opts{}; ((void)opts);
+ ASSERT_NOT_NOEXCEPT(fs::copy(p, p));
+ ASSERT_NOT_NOEXCEPT(fs::copy(p, p, ec));
+ ASSERT_NOT_NOEXCEPT(copy(p, p, opts));
+ ASSERT_NOT_NOEXCEPT(copy(p, p, opts, ec));
+}
+
+// There are 4 cases is the proposal for absolute path.
+// Each scope tests one of the cases.
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::copy(f, t);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == t
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)t); ((void)ec);
+ return true;
+#endif
+ };
+
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path dir = env.create_dir("dir");
+ const path fifo = env.create_fifo("fifo");
+ TEST_REQUIRE(is_other(fifo));
+
+ const auto test_ec = GetTestEC();
+
+ // !exists(f)
+ {
+ std::error_code ec = test_ec;
+ const path f = StaticEnv::DNE;
+ const path t = env.test_root;
+ fs::copy(f, t, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(ec != test_ec);
+ TEST_CHECK(checkThrow(f, t, ec));
+ }
+ { // equivalent(f, t) == true
+ std::error_code ec = test_ec;
+ fs::copy(file, file, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(ec != test_ec);
+ TEST_CHECK(checkThrow(file, file, ec));
+ }
+ { // is_directory(from) && is_file(to)
+ std::error_code ec = test_ec;
+ fs::copy(dir, file, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(ec != test_ec);
+ TEST_CHECK(checkThrow(dir, file, ec));
+ }
+ { // is_other(from)
+ std::error_code ec = test_ec;
+ fs::copy(fifo, dir, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(ec != test_ec);
+ TEST_CHECK(checkThrow(fifo, dir, ec));
+ }
+ { // is_other(to)
+ std::error_code ec = test_ec;
+ fs::copy(file, fifo, ec);
+ TEST_REQUIRE(ec);
+ TEST_REQUIRE(ec != test_ec);
+ TEST_CHECK(checkThrow(file, fifo, ec));
+ }
+}
+
+TEST_CASE(from_is_symlink)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path symlink = env.create_symlink(file, "sym");
+ const path dne = env.make_env_path("dne");
+
+ { // skip symlinks
+ std::error_code ec = GetTestEC();
+ fs::copy(symlink, dne, copy_options::skip_symlinks, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(dne));
+ }
+ {
+ const path dest = env.make_env_path("dest");
+ std::error_code ec = GetTestEC();
+ fs::copy(symlink, dest, copy_options::copy_symlinks, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(exists(dest));
+ TEST_CHECK(is_symlink(dest));
+ }
+ { // copy symlink but target exists
+ std::error_code ec = GetTestEC();
+ fs::copy(symlink, file, copy_options::copy_symlinks, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+ }
+ { // create symlinks but target exists
+ std::error_code ec = GetTestEC();
+ fs::copy(symlink, file, copy_options::create_symlinks, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+ }
+}
+
+TEST_CASE(from_is_regular_file)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+ { // skip copy because of directory
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec = GetTestEC();
+ fs::copy(file, dest, CO::directories_only, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(dest));
+ }
+ { // create symlink to file
+ const path dest = env.make_env_path("sym");
+ std::error_code ec = GetTestEC();
+ fs::copy(file, dest, CO::create_symlinks, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_symlink(dest));
+ TEST_CHECK(equivalent(file, canonical(dest)));
+ }
+ { // create hard link to file
+ const path dest = env.make_env_path("hardlink");
+ TEST_CHECK(hard_link_count(file) == 1);
+ std::error_code ec = GetTestEC();
+ fs::copy(file, dest, CO::create_hard_links, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(exists(dest));
+ TEST_CHECK(hard_link_count(file) == 2);
+ }
+ { // is_directory(t)
+ const path dest_dir = env.create_dir("dest_dir");
+ const path expect_dest = dest_dir / file.filename();
+ std::error_code ec = GetTestEC();
+ fs::copy(file, dest_dir, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_regular_file(expect_dest));
+ }
+ { // otherwise copy_file(from, to, ...)
+ const path dest = env.make_env_path("file_copy");
+ std::error_code ec = GetTestEC();
+ fs::copy(file, dest, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_regular_file(dest));
+ }
+}
+
+TEST_CASE(from_is_directory)
+{
+ struct FileInfo {
+ path filename;
+ std::size_t size;
+ };
+ const FileInfo files[] = {
+ {"file1", 0},
+ {"file2", 42},
+ {"file3", 300}
+ };
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path nested_dir_name = "dir2";
+ const path nested_dir = env.create_dir("dir/dir2");
+
+ for (auto& FI : files) {
+ env.create_file(dir / FI.filename, FI.size);
+ env.create_file(nested_dir / FI.filename, FI.size);
+ }
+ { // test for non-existent directory
+ const path dest = env.make_env_path("dest_dir1");
+ std::error_code ec = GetTestEC();
+ fs::copy(dir, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_directory(dest));
+ for (auto& FI : files) {
+ path created = dest / FI.filename;
+ TEST_CHECK(is_regular_file(created));
+ TEST_CHECK(file_size(created) == FI.size);
+ }
+ TEST_CHECK(!is_directory(dest / nested_dir_name));
+ }
+ { // test for existing directory
+ const path dest = env.create_dir("dest_dir2");
+ std::error_code ec = GetTestEC();
+ fs::copy(dir, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_directory(dest));
+ for (auto& FI : files) {
+ path created = dest / FI.filename;
+ TEST_CHECK(is_regular_file(created));
+ TEST_CHECK(file_size(created) == FI.size);
+ }
+ TEST_CHECK(!is_directory(dest / nested_dir_name));
+ }
+ { // test recursive copy
+ const path dest = env.make_env_path("dest_dir3");
+ std::error_code ec = GetTestEC();
+ fs::copy(dir, dest, CO::recursive, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_directory(dest));
+ const path nested_dest = dest / nested_dir_name;
+ TEST_REQUIRE(is_directory(nested_dest));
+ for (auto& FI : files) {
+ path created = dest / FI.filename;
+ path nested_created = nested_dest / FI.filename;
+ TEST_CHECK(is_regular_file(created));
+ TEST_CHECK(file_size(created) == FI.size);
+ TEST_CHECK(is_regular_file(nested_created));
+ TEST_CHECK(file_size(nested_created) == FI.size);
+ }
+ }
+}
+
+TEST_CASE(test_copy_symlinks_to_symlink_dir)
+{
+ scoped_test_env env;
+ const path file1 = env.create_file("file1", 42);
+ const path file2 = env.create_file("file2", 101);
+ const path file2_sym = env.create_symlink(file2, "file2_sym");
+ const path dir = env.create_dir("dir");
+ const path dir_sym = env.create_symlink(dir, "dir_sym");
+ {
+ std::error_code ec = GetTestEC();
+ fs::copy(file1, dir_sym, copy_options::copy_symlinks, ec);
+ TEST_CHECK(!ec);
+ const path dest = env.make_env_path("dir/file1");
+ TEST_CHECK(exists(dest));
+ TEST_CHECK(!is_symlink(dest));
+ TEST_CHECK(file_size(dest) == 42);
+ }
+}
+
+
+TEST_CASE(test_dir_create_symlink)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir1");
+ const path dest = env.make_env_path("dne");
+ {
+ std::error_code ec = GetTestEC();
+ fs::copy(dir, dest, copy_options::create_symlinks, ec);
+ TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory));
+ TEST_CHECK(!exists(dest));
+ TEST_CHECK(!is_symlink(dest));
+ }
+ {
+ std::error_code ec = GetTestEC();
+ fs::copy(dir, dest, copy_options::create_symlinks|copy_options::recursive, ec);
+ TEST_CHECK(ec == std::make_error_code(std::errc::is_a_directory));
+ TEST_CHECK(!exists(dest));
+ TEST_CHECK(!is_symlink(dest));
+ }
+}
+
+TEST_CASE(test_otherwise_no_effects_clause)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir1");
+ { // skip copy because of directory
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec;
+ fs::copy(dir, dest, CO::directories_only, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(dest));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool copy_file(const path& from, const path& to);
+// bool copy_file(const path& from, const path& to, error_code& ec) noexcept;
+// bool copy_file(const path& from, const path& to, copy_options options);
+// bool copy_file(const path& from, const path& to, copy_options options,
+// error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <chrono>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+#include <iostream>
+
+using namespace fs;
+
+using CO = fs::copy_options;
+
+TEST_SUITE(filesystem_copy_file_test_suite)
+
+TEST_CASE(test_signatures) {
+ const path p;
+ ((void)p);
+ const copy_options opts{};
+ ((void)opts);
+ std::error_code ec;
+ ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool);
+ ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p));
+ ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts));
+ ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec));
+ ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec));
+}
+
+TEST_CASE(test_error_reporting) {
+
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path file2 = env.create_file("file2", 55);
+ const path non_regular_file = env.create_fifo("non_reg");
+ const path dne = env.make_env_path("dne");
+
+ { // exists(to) && equivalent(to, from)
+ std::error_code ec;
+ TEST_CHECK(fs::copy_file(file, file, copy_options::overwrite_existing,
+ ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::file_exists));
+ ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
+
+ }
+ { // exists(to) && !(skip_existing | overwrite_existing | update_existing)
+ std::error_code ec;
+ TEST_CHECK(fs::copy_file(file, file2, ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::file_exists));
+ ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing));
+
+ }
+}
+
+TEST_CASE(non_regular_file_test) {
+ scoped_test_env env;
+ const path fifo = env.create_fifo("fifo");
+ const path dest = env.make_env_path("dest");
+ const path file = env.create_file("file", 42);
+
+ {
+ std::error_code ec = GetTestEC();
+ TEST_REQUIRE(fs::copy_file(fifo, dest, ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::not_supported));
+ TEST_CHECK(!exists(dest));
+ }
+ {
+ std::error_code ec = GetTestEC();
+ TEST_REQUIRE(fs::copy_file(file, fifo, copy_options::overwrite_existing,
+ ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::not_supported));
+ TEST_CHECK(is_fifo(fifo));
+ }
+
+}
+
+TEST_CASE(test_attributes_get_copied) {
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path dest = env.make_env_path("file2");
+ auto st = status(file);
+ perms new_perms = perms::owner_read;
+ permissions(file, new_perms);
+ std::error_code ec = GetTestEC();
+ TEST_REQUIRE(fs::copy_file(file, dest, ec) == true);
+ TEST_CHECK(!ec);
+ auto new_st = status(dest);
+ TEST_CHECK(new_st.permissions() == new_perms);
+}
+
+TEST_CASE(copy_dir_test) {
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path dest = env.create_dir("dir1");
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(fs::copy_file(file, dest, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+ ec = GetTestEC();
+ TEST_CHECK(fs::copy_file(dest, file, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+}
+
+TEST_CASE(copy_file) {
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+
+ { // !exists(to)
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec = GetTestEC();
+
+ TEST_REQUIRE(fs::copy_file(file, dest, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(dest) == 42);
+ }
+ { // exists(to) && overwrite_existing
+ const path dest = env.create_file("dest2", 55);
+ permissions(dest, perms::all);
+ permissions(file,
+ perms::group_write | perms::owner_write | perms::others_write,
+ perm_options::remove);
+
+ std::error_code ec = GetTestEC();
+ TEST_REQUIRE(fs::copy_file(file, dest, copy_options::overwrite_existing,
+ ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(dest) == 42);
+ TEST_CHECK(status(dest).permissions() == status(file).permissions());
+ }
+ { // exists(to) && update_existing
+ using Sec = std::chrono::seconds;
+ const path older = env.create_file("older_file", 1);
+
+ SleepFor(Sec(2));
+ const path from = env.create_file("update_from", 55);
+
+ SleepFor(Sec(2));
+ const path newer = env.create_file("newer_file", 2);
+
+ std::error_code ec = GetTestEC();
+ TEST_REQUIRE(
+ fs::copy_file(from, older, copy_options::update_existing, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(older) == 55);
+
+ TEST_REQUIRE(
+ fs::copy_file(from, newer, copy_options::update_existing, ec) == false);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(newer) == 2);
+ }
+ { // skip_existing
+ const path file2 = env.create_file("file2", 55);
+ std::error_code ec = GetTestEC();
+ TEST_REQUIRE(fs::copy_file(file, file2, copy_options::skip_existing, ec) ==
+ false);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(file2) == 55);
+ }
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+// REQUIRES: long_tests
+
+// <filesystem>
+
+// bool copy_file(const path& from, const path& to);
+// bool copy_file(const path& from, const path& to, error_code& ec) noexcept;
+// bool copy_file(const path& from, const path& to, copy_options options);
+// bool copy_file(const path& from, const path& to, copy_options options,
+// error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <chrono>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_copy_file_test_suite)
+
+static std::string random_hex_chars(uintmax_t size) {
+ std::string data;
+ data.reserve(size);
+ for (uintmax_t I = 0; I < size; ++I)
+ data.push_back(random_utils::random_hex_char());
+ return data;
+}
+
+// This test is intended to test 'sendfile's 2gb limit for a single call, and
+// to ensure that libc++ correctly copies files larger than that limit.
+// However it requires allocating ~5GB of filesystem space. This might not
+// be acceptable on all systems.
+TEST_CASE(large_file) {
+ using namespace fs;
+ constexpr uintmax_t sendfile_size_limit = 2147479552ull;
+ constexpr uintmax_t additional_size = 1024;
+ constexpr uintmax_t test_file_size = sendfile_size_limit + additional_size;
+ static_assert(test_file_size > sendfile_size_limit, "");
+
+ scoped_test_env env;
+
+ // Check that we have more than sufficient room to create the files needed
+ // to perform the test.
+ if (space(env.test_root).available < 3 * test_file_size) {
+ TEST_UNSUPPORTED();
+ }
+
+ // Use python to create a file right at the size limit.
+ const path file = env.create_file("source", sendfile_size_limit);
+ // Create some random data that looks different than the data before the
+ // size limit.
+ const std::string additional_data = random_hex_chars(additional_size);
+ // Append this known data to the end of the source file.
+ {
+ std::ofstream outf(file.native(), std::ios_base::app);
+ TEST_REQUIRE(outf.good());
+ outf << additional_data;
+ TEST_REQUIRE(outf);
+ }
+ TEST_REQUIRE(file_size(file) == test_file_size);
+ const path dest = env.make_env_path("dest");
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(copy_file(file, dest, ec));
+ TEST_CHECK(!ec);
+
+ TEST_REQUIRE(is_regular_file(dest));
+ TEST_CHECK(file_size(dest) == test_file_size);
+
+ // Read the data from the end of the destination file, and ensure it matches
+ // the data at the end of the source file.
+ std::string out_data;
+ out_data.reserve(additional_size);
+ {
+ std::ifstream dest_file(dest.native());
+ TEST_REQUIRE(dest_file);
+ dest_file.seekg(sendfile_size_limit);
+ TEST_REQUIRE(dest_file);
+ dest_file >> out_data;
+ TEST_CHECK(dest_file.eof());
+ }
+ TEST_CHECK(out_data.size() == additional_data.size());
+ TEST_CHECK(out_data == additional_data);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void copy_symlink(const path& existing_symlink, const path& new_symlink);
+// void copy_symlink(const path& existing_symlink, const path& new_symlink,
+// error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_copy_symlink_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(fs::copy_symlink(p, p));
+ ASSERT_NOEXCEPT(fs::copy_symlink(p, p, ec));
+}
+
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::copy_symlink(f, t);
+ return true;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)t); ((void)ec);
+ return true;
+#endif
+ };
+
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path file2 = env.create_file("file2", 55);
+ const path sym = env.create_symlink(file, "sym");
+ const path dir = env.create_dir("dir");
+ const path dne = env.make_env_path("dne");
+ { // from is a file, not a symlink
+ std::error_code ec;
+ fs::copy_symlink(file, dne, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(checkThrow(file, dne, ec));
+ }
+ { // from is a file, not a symlink
+ std::error_code ec;
+ fs::copy_symlink(dir, dne, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(checkThrow(dir, dne, ec));
+ }
+ { // destination exists
+ std::error_code ec;
+ fs::copy_symlink(sym, file2, ec);
+ TEST_REQUIRE(ec);
+ }
+}
+
+TEST_CASE(copy_symlink_basic)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dir_sym = env.create_symlink(dir, "dir_sym");
+ const path file = env.create_file("file", 42);
+ const path file_sym = env.create_symlink(file, "file_sym");
+ { // test for directory symlinks
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec;
+ fs::copy_symlink(dir_sym, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_symlink(dest));
+ TEST_CHECK(equivalent(dest, dir));
+ }
+ { // test for file symlinks
+ const path dest = env.make_env_path("dest2");
+ std::error_code ec;
+ fs::copy_symlink(file_sym, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_symlink(dest));
+ TEST_CHECK(equivalent(dest, file));
+ }
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool create_directories(const path& p);
+// bool create_directories(const path& p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_create_directories_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::create_directories(p)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::create_directories(p, ec)), bool);
+ ASSERT_NOT_NOEXCEPT(fs::create_directories(p));
+ ASSERT_NOT_NOEXCEPT(fs::create_directories(p, ec));
+}
+
+TEST_CASE(create_existing_directory)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir1");
+ std::error_code ec;
+ TEST_CHECK(fs::create_directories(dir, ec) == false);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(dir));
+}
+
+TEST_CASE(create_directory_one_level)
+{
+ scoped_test_env env;
+ const path dir = env.make_env_path("dir1");
+ std::error_code ec;
+ TEST_CHECK(fs::create_directories(dir, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(dir));
+}
+
+TEST_CASE(create_directories_multi_level)
+{
+ scoped_test_env env;
+ const path dir = env.make_env_path("dir1/dir2/dir3");
+ std::error_code ec;
+ TEST_CHECK(fs::create_directories(dir, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(dir));
+}
+
+TEST_CASE(create_directory_symlinks) {
+ scoped_test_env env;
+ const path root = env.create_dir("dir");
+ const path sym_dest_dead = env.make_env_path("dead");
+ const path dead_sym = env.create_symlink(sym_dest_dead, "dir/sym_dir");
+ const path target = env.make_env_path("dir/sym_dir/foo");
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(create_directories(target, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(!exists(sym_dest_dead));
+ TEST_CHECK(!exists(dead_sym));
+ }
+}
+
+
+TEST_CASE(create_directory_through_symlinks) {
+ scoped_test_env env;
+ const path root = env.create_dir("dir");
+ const path sym_dir = env.create_symlink(root, "sym_dir");
+ const path target = env.make_env_path("sym_dir/foo");
+ const path resolved_target = env.make_env_path("dir/foo");
+ TEST_REQUIRE(is_directory(sym_dir));
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(create_directories(target, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(target));
+ TEST_CHECK(is_directory(resolved_target));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool create_directory(const path& p);
+// bool create_directory(const path& p, error_code& ec) noexcept;
+// bool create_directory(const path& p, const path& attr);
+// bool create_directory(const path& p, const path& attr, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+using namespace fs;
+
+fs::perms read_umask() {
+ mode_t old_mask = umask(0);
+ umask(old_mask); // reset the mask to the old value.
+ return static_cast<fs::perms>(old_mask);
+}
+
+TEST_SUITE(filesystem_create_directory_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::create_directory(p)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::create_directory(p, ec)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p, ec)), bool);
+ ASSERT_NOT_NOEXCEPT(fs::create_directory(p));
+ ASSERT_NOEXCEPT(fs::create_directory(p, ec));
+ ASSERT_NOT_NOEXCEPT(fs::create_directory(p, p));
+ ASSERT_NOEXCEPT(fs::create_directory(p, p, ec));
+}
+
+
+TEST_CASE(create_existing_directory)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir1");
+ std::error_code ec;
+ TEST_CHECK(fs::create_directory(dir, ec) == false);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(dir));
+ // Test throwing version
+ TEST_CHECK(fs::create_directory(dir) == false);
+}
+
+TEST_CASE(create_directory_one_level)
+{
+ scoped_test_env env;
+ const path dir = env.make_env_path("dir1");
+ std::error_code ec;
+ TEST_CHECK(fs::create_directory(dir, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(dir));
+
+ auto st = status(dir);
+ const perms expect_perms = perms::all & ~(read_umask());
+ TEST_CHECK((st.permissions() & perms::all) == expect_perms);
+}
+
+TEST_CASE(create_directory_multi_level)
+{
+ scoped_test_env env;
+ const path dir = env.make_env_path("dir1/dir2");
+ const path dir1 = env.make_env_path("dir1");
+ std::error_code ec;
+ TEST_CHECK(fs::create_directory(dir, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(!is_directory(dir));
+ TEST_CHECK(!is_directory(dir1));
+}
+
+TEST_CASE(dest_is_file)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(fs::create_directory(file, ec) == false);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_regular_file(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool create_directory(const path& p, const path& attr);
+// bool create_directory(const path& p, const path& attr, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_create_directory_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::create_directory(p, p, ec)), bool);
+ ASSERT_NOT_NOEXCEPT(fs::create_directory(p, p));
+ ASSERT_NOEXCEPT(fs::create_directory(p, p, ec));
+}
+
+TEST_CASE(create_existing_directory)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir1");
+ const path dir2 = env.create_dir("dir2");
+
+ const perms orig_p = status(dir).permissions();
+ permissions(dir2, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(fs::create_directory(dir, dir2, ec) == false);
+ TEST_CHECK(!ec);
+
+ // Check that the permissions were unchanged
+ TEST_CHECK(orig_p == status(dir).permissions());
+
+ // Test throwing version
+ TEST_CHECK(fs::create_directory(dir, dir2) == false);
+}
+
+TEST_CASE(create_directory_one_level)
+{
+ scoped_test_env env;
+ // Remove setgid which mkdir would inherit
+ permissions(env.test_root, perms::set_gid, perm_options::remove);
+
+ const path dir = env.make_env_path("dir1");
+ const path attr_dir = env.create_dir("dir2");
+ permissions(attr_dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == true);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_directory(dir));
+
+ // Check that the new directory has the same permissions as attr_dir
+ auto st = status(dir);
+ TEST_CHECK(st.permissions() == perms::none);
+}
+
+TEST_CASE(create_directory_multi_level)
+{
+ scoped_test_env env;
+ const path dir = env.make_env_path("dir1/dir2");
+ const path dir1 = env.make_env_path("dir1");
+ const path attr_dir = env.create_dir("attr_dir");
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+ TEST_CHECK(!is_directory(dir));
+ TEST_CHECK(!is_directory(dir1));
+}
+
+TEST_CASE(dest_is_file)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path attr_dir = env.create_dir("attr_dir");
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(fs::create_directory(file, attr_dir, ec) == false);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_regular_file(file));
+}
+
+TEST_CASE(attr_dir_is_invalid) {
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path dest = env.make_env_path("dir");
+ const path dne = env.make_env_path("dne");
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(create_directory(dest, file, ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::not_a_directory));
+ }
+ TEST_REQUIRE(!exists(dest));
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(create_directory(dest, dne, ec) == false);
+ TEST_CHECK(ErrorIs(ec, std::errc::not_a_directory));
+ }
+}
+
+TEST_CASE(dest_is_symlink) {
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path sym = env.create_symlink("dne_sym", "dne_sym_name");
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(create_directory(sym, dir, ec) == false);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void create_directory_symlink(const path& existing_symlink, const path& new_symlink);
+// void create_directory_symlink(const path& existing_symlink, const path& new_symlink,
+// error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_create_directory_symlink_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(fs::create_directory_symlink(p, p));
+ ASSERT_NOEXCEPT(fs::create_directory_symlink(p, p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path file2 = env.create_file("file2", 55);
+ const path sym = env.create_symlink(file, "sym");
+ { // destination exists
+ std::error_code ec;
+ fs::create_directory_symlink(sym, file2, ec);
+ TEST_REQUIRE(ec);
+ }
+}
+
+TEST_CASE(create_directory_symlink_basic)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dir_sym = env.create_symlink(dir, "dir_sym");
+
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec;
+ fs::create_directory_symlink(dir_sym, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_symlink(dest));
+ TEST_CHECK(equivalent(dest, dir));
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void create_hard_link(const path& existing_symlink, const path& new_symlink);
+// void create_hard_link(const path& existing_symlink, const path& new_symlink,
+// error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_create_hard_link_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(fs::create_hard_link(p, p));
+ ASSERT_NOEXCEPT(fs::create_hard_link(p, p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path file2 = env.create_file("file2", 55);
+ const path sym = env.create_symlink(file, "sym");
+ { // destination exists
+ std::error_code ec;
+ fs::create_hard_link(sym, file2, ec);
+ TEST_REQUIRE(ec);
+ }
+}
+
+TEST_CASE(create_file_hard_link)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file");
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec;
+ TEST_CHECK(hard_link_count(file) == 1);
+ fs::create_hard_link(file, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(exists(dest));
+ TEST_CHECK(equivalent(dest, file));
+ TEST_CHECK(hard_link_count(file) == 2);
+}
+
+TEST_CASE(create_directory_hard_link_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dest = env.make_env_path("dest2");
+ std::error_code ec;
+
+ fs::create_hard_link(dir, dest, ec);
+ TEST_REQUIRE(ec);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void create_symlink(const path& existing_symlink, const path& new_symlink);
+// void create_symlink(const path& existing_symlink, const path& new_symlink,
+// error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_create_symlink_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(fs::create_symlink(p, p));
+ ASSERT_NOEXCEPT(fs::create_symlink(p, p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path file2 = env.create_file("file2", 55);
+ const path sym = env.create_symlink(file, "sym");
+ { // destination exists
+ std::error_code ec;
+ fs::create_symlink(sym, file2, ec);
+ TEST_REQUIRE(ec);
+ }
+}
+
+TEST_CASE(create_symlink_basic)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path file_sym = env.create_symlink(file, "file_sym");
+ const path dir = env.create_dir("dir");
+ const path dir_sym = env.create_symlink(dir, "dir_sym");
+ {
+ const path dest = env.make_env_path("dest1");
+ std::error_code ec;
+ fs::create_symlink(file_sym, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_symlink(dest));
+ TEST_CHECK(equivalent(dest, file));
+ }
+ {
+ const path dest = env.make_env_path("dest2");
+ std::error_code ec;
+ fs::create_symlink(dir_sym, dest, ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(is_symlink(dest));
+ TEST_CHECK(equivalent(dest, dir));
+ }
+}
+
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path current_path();
+// path current_path(error_code& ec);
+// void current_path(path const&);
+// void current_path(path const&, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_current_path_path_test_suite)
+
+TEST_CASE(current_path_signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(current_path());
+ ASSERT_NOT_NOEXCEPT(current_path(ec));
+ ASSERT_NOT_NOEXCEPT(current_path(p));
+ ASSERT_NOEXCEPT(current_path(p, ec));
+}
+
+TEST_CASE(current_path_test)
+{
+ std::error_code ec;
+ const path p = current_path(ec);
+ TEST_REQUIRE(!ec);
+ TEST_CHECK(p.is_absolute());
+ TEST_CHECK(is_directory(p));
+
+ const path p2 = current_path();
+ TEST_CHECK(p2 == p);
+}
+
+TEST_CASE(current_path_after_change_test)
+{
+ const path new_path = StaticEnv::Dir;
+ current_path(new_path);
+ TEST_CHECK(current_path() == new_path);
+}
+
+TEST_CASE(current_path_is_file_test)
+{
+ const path p = StaticEnv::File;
+ std::error_code ec;
+ const path old_p = current_path();
+ current_path(p, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(old_p == current_path());
+}
+
+TEST_CASE(set_to_non_absolute_path)
+{
+ const path base = StaticEnv::Dir;
+ current_path(base);
+ const path p = StaticEnv::Dir2.filename();
+ std::error_code ec;
+ current_path(p, ec);
+ TEST_CHECK(!ec);
+ const path new_cwd = current_path();
+ TEST_CHECK(new_cwd == StaticEnv::Dir2);
+ TEST_CHECK(new_cwd.is_absolute());
+}
+
+TEST_CASE(set_to_empty)
+{
+ const path p = "";
+ std::error_code ec;
+ const path old_p = current_path();
+ current_path(p, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(old_p == current_path());
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool equivalent(path const& lhs, path const& rhs);
+// bool equivalent(path const& lhs, path const& rhs, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(equivalent_test_suite)
+
+TEST_CASE(signature_test) {
+ const path p;
+ ((void)p);
+ std::error_code ec;
+ ((void)ec);
+ ASSERT_NOEXCEPT(equivalent(p, p, ec));
+ ASSERT_NOT_NOEXCEPT(equivalent(p, p));
+}
+
+TEST_CASE(equivalent_test) {
+ struct TestCase {
+ path lhs;
+ path rhs;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {StaticEnv::Dir, StaticEnv::Dir, true},
+ {StaticEnv::File, StaticEnv::Dir, false},
+ {StaticEnv::Dir, StaticEnv::SymlinkToDir, true},
+ {StaticEnv::Dir, StaticEnv::SymlinkToFile, false},
+ {StaticEnv::File, StaticEnv::File, true},
+ {StaticEnv::File, StaticEnv::SymlinkToFile, true},
+ };
+ for (auto& TC : testCases) {
+ std::error_code ec;
+ TEST_CHECK(equivalent(TC.lhs, TC.rhs, ec) == TC.expect);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(equivalent_reports_error_if_input_dne) {
+ const path E = StaticEnv::File;
+ const path DNE = StaticEnv::DNE;
+ { // Test that an error is reported when either of the paths don't exist
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(equivalent(E, DNE, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+ }
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(equivalent(DNE, E, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+ }
+ {
+ TEST_CHECK_THROW(filesystem_error, equivalent(DNE, E));
+ TEST_CHECK_THROW(filesystem_error, equivalent(E, DNE));
+ }
+ { // Test that an exception is thrown if both paths do not exist.
+ TEST_CHECK_THROW(filesystem_error, equivalent(DNE, DNE));
+ }
+ {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(equivalent(DNE, DNE, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+ }
+}
+
+TEST_CASE(equivalent_hardlink_succeeds) {
+ scoped_test_env env;
+ path const file = env.create_file("file", 42);
+ const path hl1 = env.create_hardlink(file, "hl1");
+ const path hl2 = env.create_hardlink(file, "hl2");
+ TEST_CHECK(equivalent(file, hl1));
+ TEST_CHECK(equivalent(file, hl2));
+ TEST_CHECK(equivalent(hl1, hl2));
+}
+
+TEST_CASE(equivalent_is_other_succeeds) {
+ scoped_test_env env;
+ path const file = env.create_file("file", 42);
+ const path fifo1 = env.create_fifo("fifo1");
+ const path fifo2 = env.create_fifo("fifo2");
+ // Required to test behavior for inputs where is_other(p) is true.
+ TEST_REQUIRE(is_other(fifo1));
+ TEST_CHECK(!equivalent(file, fifo1));
+ TEST_CHECK(!equivalent(fifo2, file));
+ TEST_CHECK(!equivalent(fifo1, fifo2));
+ TEST_CHECK(equivalent(fifo1, fifo1));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool exists(file_status s) noexcept
+// bool exists(path const& p);
+// bool exists(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(exists_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(exists(s));
+ ASSERT_NOEXCEPT(exists(p, ec));
+ ASSERT_NOT_NOEXCEPT(exists(p));
+}
+
+TEST_CASE(exists_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, true},
+ {file_type::directory, true},
+ {file_type::symlink, true},
+ {file_type::block, true},
+ {file_type::character, true},
+ {file_type::fifo, true},
+ {file_type::socket, true},
+ {file_type::unknown, true}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(exists(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(exists(p) == false);
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(exists(p, ec) == false);
+ TEST_CHECK(!ec);
+}
+
+TEST_CASE(test_exists_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(exists(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, exists(file));
+}
+
+TEST_CASE(test_name_too_long) {
+ std::string long_name(2500, 'a');
+ const path file(long_name);
+
+ std::error_code ec;
+ TEST_CHECK(exists(file, ec) == false);
+ TEST_CHECK(ec);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// uintmax_t file_size(const path& p);
+// uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(file_size_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(file_size(p)), uintmax_t);
+ ASSERT_SAME_TYPE(decltype(file_size(p, ec)), uintmax_t);
+ ASSERT_NOT_NOEXCEPT(file_size(p));
+ ASSERT_NOEXCEPT(file_size(p, ec));
+}
+
+TEST_CASE(file_size_empty_test)
+{
+ const path p = StaticEnv::EmptyFile;
+ TEST_CHECK(file_size(p) == 0);
+ std::error_code ec;
+ TEST_CHECK(file_size(p, ec) == 0);
+}
+
+TEST_CASE(file_size_non_empty)
+{
+ scoped_test_env env;
+ const path p = env.create_file("file", 42);
+ TEST_CHECK(file_size(p) == 42);
+ std::error_code ec;
+ TEST_CHECK(file_size(p, ec) == 42);
+}
+
+TEST_CASE(symlink_test_case)
+{
+ const path p = StaticEnv::File;
+ const path p2 = StaticEnv::SymlinkToFile;
+ TEST_CHECK(file_size(p) == file_size(p2));
+}
+
+TEST_CASE(file_size_error_cases)
+{
+ struct {
+ path p;
+ std::errc expected_err;
+ } TestCases[] = {
+ {StaticEnv::Dir, std::errc::is_a_directory},
+ {StaticEnv::SymlinkToDir, std::errc::is_a_directory},
+ {StaticEnv::BadSymlink, std::errc::no_such_file_or_directory},
+ {StaticEnv::DNE, std::errc::no_such_file_or_directory},
+ {"", std::errc::no_such_file_or_directory}};
+ const uintmax_t expect = static_cast<uintmax_t>(-1);
+ for (auto& TC : TestCases) {
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(file_size(TC.p, ec) == expect);
+ TEST_CHECK(ErrorIs(ec, TC.expected_err));
+
+ ExceptionChecker Checker(TC.p, TC.expected_err, "file_size");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, file_size(TC.p));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// uintmax_t hard_link_count(const path& p);
+// uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(hard_link_count_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(hard_link_count(p)), uintmax_t);
+ ASSERT_SAME_TYPE(decltype(hard_link_count(p, ec)), uintmax_t);
+ ASSERT_NOT_NOEXCEPT(hard_link_count(p));
+ ASSERT_NOEXCEPT(hard_link_count(p, ec));
+}
+
+TEST_CASE(hard_link_count_for_file)
+{
+ TEST_CHECK(hard_link_count(StaticEnv::File) == 1);
+ std::error_code ec;
+ TEST_CHECK(hard_link_count(StaticEnv::File, ec) == 1);
+}
+
+TEST_CASE(hard_link_count_for_directory)
+{
+ uintmax_t DirExpect = 3; // hard link from . .. and Dir2
+ uintmax_t Dir3Expect = 2; // hard link from . ..
+ uintmax_t DirExpectAlt = DirExpect;
+ uintmax_t Dir3ExpectAlt = Dir3Expect;
+#if defined(__APPLE__)
+ // Filesystems formatted with case sensitive hfs+ behave unixish as
+ // expected. Normal hfs+ filesystems report the number of directory
+ // entries instead.
+ DirExpectAlt = 5; // . .. Dir2 file1 file2
+ Dir3Expect = 3; // . .. file5
+#endif
+ TEST_CHECK(hard_link_count(StaticEnv::Dir) == DirExpect ||
+ hard_link_count(StaticEnv::Dir) == DirExpectAlt ||
+ hard_link_count(StaticEnv::Dir) == 1);
+ TEST_CHECK(hard_link_count(StaticEnv::Dir3) == Dir3Expect ||
+ hard_link_count(StaticEnv::Dir3) == Dir3ExpectAlt ||
+ hard_link_count(StaticEnv::Dir3) == 1);
+
+ std::error_code ec;
+ TEST_CHECK(hard_link_count(StaticEnv::Dir, ec) == DirExpect ||
+ hard_link_count(StaticEnv::Dir, ec) == DirExpectAlt ||
+ hard_link_count(StaticEnv::Dir) == 1);
+ TEST_CHECK(hard_link_count(StaticEnv::Dir3, ec) == Dir3Expect ||
+ hard_link_count(StaticEnv::Dir3, ec) == Dir3ExpectAlt ||
+ hard_link_count(StaticEnv::Dir3) == 1);
+}
+TEST_CASE(hard_link_count_increments_test)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ TEST_CHECK(hard_link_count(file) == 1);
+
+ env.create_hardlink(file, "file_hl");
+ TEST_CHECK(hard_link_count(file) == 2);
+}
+
+
+TEST_CASE(hard_link_count_error_cases)
+{
+ const path testCases[] = {
+ StaticEnv::BadSymlink,
+ StaticEnv::DNE
+ };
+ const uintmax_t expect = static_cast<uintmax_t>(-1);
+ for (auto& TC : testCases) {
+ std::error_code ec;
+ TEST_CHECK(hard_link_count(TC, ec) == expect);
+ TEST_CHECK(ec);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_block_file(file_status s) noexcept
+// bool is_block_file(path const& p);
+// bool is_block_file(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_block_file_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_block_file(s));
+ ASSERT_NOEXCEPT(is_block_file(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_block_file(p));
+}
+
+TEST_CASE(is_block_file_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, false},
+ {file_type::symlink, false},
+ {file_type::block, true},
+ {file_type::character, false},
+ {file_type::fifo, false},
+ {file_type::socket, false},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_block_file(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_block_file(p) == false);
+}
+
+TEST_CASE(test_is_block_file_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_block_file(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_block_file(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_character_file(file_status s) noexcept
+// bool is_character_file(path const& p);
+// bool is_character_file(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_character_file_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_character_file(s));
+ ASSERT_NOEXCEPT(is_character_file(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_character_file(p));
+}
+
+TEST_CASE(is_character_file_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, false},
+ {file_type::symlink, false},
+ {file_type::block, false},
+ {file_type::character, true},
+ {file_type::fifo, false},
+ {file_type::socket, false},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_character_file(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_character_file(p) == false);
+}
+
+TEST_CASE(test_is_character_file_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_character_file(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_character_file(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_directory(file_status s) noexcept
+// bool is_directory(path const& p);
+// bool is_directory(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_directory_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_directory(s));
+ ASSERT_NOEXCEPT(is_directory(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_directory(p));
+}
+
+TEST_CASE(is_directory_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, true},
+ {file_type::symlink, false},
+ {file_type::block, false},
+ {file_type::character, false},
+ {file_type::fifo, false},
+ {file_type::socket, false},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_directory(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_directory(p) == false);
+}
+
+TEST_CASE(static_env_test)
+{
+ TEST_CHECK(is_directory(StaticEnv::Dir));
+ TEST_CHECK(is_directory(StaticEnv::SymlinkToDir));
+ TEST_CHECK(!is_directory(StaticEnv::File));
+}
+
+TEST_CASE(test_is_directory_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dir2 = env.create_dir("dir/dir2");
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_directory(dir2, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_directory(dir2));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_empty(path const& p);
+// bool is_empty(path const& p, std::error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_empty_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(is_empty(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_empty(p));
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ std::error_code ec;
+ TEST_CHECK(is_empty(p, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK_THROW(filesystem_error, is_empty(p));
+}
+
+TEST_CASE(test_is_empty_directory)
+{
+ TEST_CHECK(!is_empty(StaticEnv::Dir));
+ TEST_CHECK(!is_empty(StaticEnv::SymlinkToDir));
+}
+
+TEST_CASE(test_is_empty_directory_dynamic)
+{
+ scoped_test_env env;
+ TEST_CHECK(is_empty(env.test_root));
+ env.create_file("foo", 42);
+ TEST_CHECK(!is_empty(env.test_root));
+}
+
+TEST_CASE(test_is_empty_file)
+{
+ TEST_CHECK(is_empty(StaticEnv::EmptyFile));
+ TEST_CHECK(!is_empty(StaticEnv::NonEmptyFile));
+}
+
+TEST_CASE(test_is_empty_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dir2 = env.create_dir("dir/dir2");
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_empty(dir2, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_empty(dir2));
+}
+
+TEST_CASE(test_directory_access_denied)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file1 = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(is_empty(dir, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+
+ TEST_CHECK_THROW(filesystem_error, is_empty(dir));
+}
+
+
+TEST_CASE(test_fifo_fails)
+{
+ scoped_test_env env;
+ const path fifo = env.create_fifo("fifo");
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(is_empty(fifo, ec) == false);
+ TEST_CHECK(ec);
+ TEST_CHECK(ec != GetTestEC());
+
+ TEST_CHECK_THROW(filesystem_error, is_empty(fifo));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_fifo(file_status s) noexcept
+// bool is_fifo(path const& p);
+// bool is_fifo(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_fifo_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_fifo(s));
+ ASSERT_NOEXCEPT(is_fifo(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_fifo(p));
+}
+
+TEST_CASE(is_fifo_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, false},
+ {file_type::symlink, false},
+ {file_type::block, false},
+ {file_type::character, false},
+ {file_type::fifo, true},
+ {file_type::socket, false},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_fifo(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_fifo(p) == false);
+}
+
+TEST_CASE(test_is_fifo_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_fifo(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_fifo(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_other(file_status s) noexcept
+// bool is_other(path const& p);
+// bool is_other(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_other_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_other(s));
+ ASSERT_NOEXCEPT(is_other(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_other(p));
+}
+
+TEST_CASE(is_other_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, false},
+ {file_type::symlink, false},
+ {file_type::block, true},
+ {file_type::character, true},
+ {file_type::fifo, true},
+ {file_type::socket, true},
+ {file_type::unknown, true}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_other(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_other(p) == false);
+}
+
+TEST_CASE(test_is_other_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_other(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_other(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_regular_file(file_status s) noexcept
+// bool is_regular_file(path const& p);
+// bool is_regular_file(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_regular_file_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_regular_file(s));
+ ASSERT_NOEXCEPT(is_regular_file(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_regular_file(p));
+}
+
+TEST_CASE(is_regular_file_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, true},
+ {file_type::directory, false},
+ {file_type::symlink, false},
+ {file_type::block, false},
+ {file_type::character, false},
+ {file_type::fifo, false},
+ {file_type::socket, false},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_regular_file(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_regular_file(p) == false);
+ std::error_code ec;
+ TEST_CHECK(is_regular_file(p, ec) == false);
+ TEST_CHECK(ec);
+}
+
+TEST_CASE(test_is_regular_file_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_regular_file(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_regular_file(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_socket(file_status s) noexcept
+// bool is_socket(path const& p);
+// bool is_socket(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_socket_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_socket(s));
+ ASSERT_NOEXCEPT(is_socket(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_socket(p));
+}
+
+TEST_CASE(is_socket_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, false},
+ {file_type::symlink, false},
+ {file_type::block, false},
+ {file_type::character, false},
+ {file_type::fifo, false},
+ {file_type::socket, true},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_socket(s) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_socket(p) == false);
+}
+
+TEST_CASE(test_is_socket_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_socket(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_socket(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool is_symlink(file_status s) noexcept
+// bool is_symlink(path const& p);
+// bool is_symlink(path const& p, std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(is_symlink_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOEXCEPT(is_symlink(s));
+ ASSERT_NOEXCEPT(is_symlink(p, ec));
+ ASSERT_NOT_NOEXCEPT(is_symlink(p));
+}
+
+TEST_CASE(is_symlink_status_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, false},
+ {file_type::regular, false},
+ {file_type::directory, false},
+ {file_type::symlink, true},
+ {file_type::block, false},
+ {file_type::character, false},
+ {file_type::fifo, false},
+ {file_type::socket, false},
+ {file_type::unknown, false}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(is_symlink(s) == TC.expect);
+ }
+}
+
+TEST_CASE(static_env_test)
+{
+ struct TestCase {
+ path p;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {StaticEnv::File, false},
+ {StaticEnv::Dir, false},
+ {StaticEnv::SymlinkToFile, true},
+ {StaticEnv::SymlinkToDir, true},
+ {StaticEnv::BadSymlink, true}
+ };
+ for (auto& TC : testCases) {
+ TEST_CHECK(is_symlink(TC.p) == TC.expect);
+ }
+}
+
+TEST_CASE(test_exist_not_found)
+{
+ const path p = StaticEnv::DNE;
+ TEST_CHECK(is_symlink(p) == false);
+ std::error_code ec;
+ TEST_CHECK(is_symlink(p, ec) == false);
+ TEST_CHECK(ec);
+}
+
+TEST_CASE(test_is_symlink_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec;
+ TEST_CHECK(is_symlink(file, ec) == false);
+ TEST_CHECK(ec);
+
+ TEST_CHECK_THROW(filesystem_error, is_symlink(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// file_time_type last_write_time(const path& p);
+// file_time_type last_write_time(const path& p, std::error_code& ec) noexcept;
+// void last_write_time(const path& p, file_time_type new_time);
+// void last_write_time(const path& p, file_time_type new_type,
+// std::error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <chrono>
+#include <fstream>
+#include <cstdlib>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+#include <sys/stat.h>
+#include <iostream>
+
+#include <fcntl.h>
+#include <sys/time.h>
+
+using namespace fs;
+
+using TimeSpec = struct ::timespec;
+using StatT = struct ::stat;
+
+using Sec = std::chrono::duration<file_time_type::rep>;
+using Hours = std::chrono::hours;
+using Minutes = std::chrono::minutes;
+using MicroSec = std::chrono::duration<file_time_type::rep, std::micro>;
+using NanoSec = std::chrono::duration<file_time_type::rep, std::nano>;
+using std::chrono::duration_cast;
+
+#if defined(__APPLE__)
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
+#else
+TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
+TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
+#endif
+
+bool ConvertToTimeSpec(TimeSpec& ts, file_time_type ft) {
+ using SecFieldT = decltype(TimeSpec::tv_sec);
+ using NSecFieldT = decltype(TimeSpec::tv_nsec);
+ using SecLim = std::numeric_limits<SecFieldT>;
+ using NSecLim = std::numeric_limits<NSecFieldT>;
+
+ auto secs = duration_cast<Sec>(ft.time_since_epoch());
+ auto nsecs = duration_cast<NanoSec>(ft.time_since_epoch() - secs);
+ if (nsecs.count() < 0) {
+ if (Sec::min().count() > SecLim::min()) {
+ secs += Sec(1);
+ nsecs -= Sec(1);
+ } else {
+ nsecs = NanoSec(0);
+ }
+ }
+ if (SecLim::max() < secs.count() || SecLim::min() > secs.count())
+ return false;
+ if (NSecLim::max() < nsecs.count() || NSecLim::min() > nsecs.count())
+ return false;
+ ts.tv_sec = secs.count();
+ ts.tv_nsec = nsecs.count();
+ return true;
+}
+
+bool ConvertFromTimeSpec(file_time_type& ft, TimeSpec ts) {
+ auto secs_part = duration_cast<file_time_type::duration>(Sec(ts.tv_sec));
+ if (duration_cast<Sec>(secs_part).count() != ts.tv_sec)
+ return false;
+ auto subsecs = duration_cast<file_time_type::duration>(NanoSec(ts.tv_nsec));
+ auto dur = secs_part + subsecs;
+ if (dur < secs_part && subsecs.count() >= 0)
+ return false;
+ ft = file_time_type(dur);
+ return true;
+}
+
+bool CompareTimeExact(TimeSpec ts, TimeSpec ts2) {
+ return ts2.tv_sec == ts.tv_sec && ts2.tv_nsec == ts.tv_nsec;
+}
+bool CompareTimeExact(file_time_type ft, TimeSpec ts) {
+ TimeSpec ts2 = {};
+ if (!ConvertToTimeSpec(ts2, ft))
+ return false;
+ return CompareTimeExact(ts, ts2);
+}
+bool CompareTimeExact(TimeSpec ts, file_time_type ft) {
+ return CompareTimeExact(ft, ts);
+}
+
+struct Times {
+ TimeSpec access, write;
+};
+
+Times GetTimes(path const& p) {
+ using Clock = file_time_type::clock;
+ StatT st;
+ if (::stat(p.c_str(), &st) == -1) {
+ std::error_code ec(errno, std::generic_category());
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ throw ec;
+#else
+ std::cerr << ec.message() << std::endl;
+ std::exit(EXIT_FAILURE);
+#endif
+ }
+ return {extract_atime(st), extract_mtime(st)};
+}
+
+TimeSpec LastAccessTime(path const& p) { return GetTimes(p).access; }
+
+TimeSpec LastWriteTime(path const& p) { return GetTimes(p).write; }
+
+std::pair<TimeSpec, TimeSpec> GetSymlinkTimes(path const& p) {
+ using Clock = file_time_type::clock;
+ StatT st;
+ if (::lstat(p.c_str(), &st) == -1) {
+ std::error_code ec(errno, std::generic_category());
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ throw ec;
+#else
+ std::cerr << ec.message() << std::endl;
+ std::exit(EXIT_FAILURE);
+#endif
+ }
+ return {extract_atime(st), extract_mtime(st)};
+}
+
+namespace {
+
+// In some configurations, the comparison is tautological and the test is valid.
+// We disable the warning so that we can actually test it regardless. Also, that
+// diagnostic is pretty new, so also don't fail if old clang does not support it
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wtautological-constant-compare"
+#endif
+
+static const bool SupportsNegativeTimes = [] {
+ using namespace std::chrono;
+ std::error_code ec;
+ TimeSpec old_write_time, new_write_time;
+ { // WARNING: Do not assert in this scope.
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ old_write_time = LastWriteTime(file);
+ file_time_type tp(seconds(-5));
+ fs::last_write_time(file, tp, ec);
+ new_write_time = LastWriteTime(file);
+ }
+
+ return !ec && new_write_time.tv_sec < 0;
+}();
+
+static const bool SupportsMaxTime = [] {
+ using namespace std::chrono;
+ TimeSpec max_ts = {};
+ if (!ConvertToTimeSpec(max_ts, file_time_type::max()))
+ return false;
+
+ std::error_code ec;
+ TimeSpec old_write_time, new_write_time;
+ { // WARNING: Do not assert in this scope.
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ old_write_time = LastWriteTime(file);
+ file_time_type tp = file_time_type::max();
+ fs::last_write_time(file, tp, ec);
+ new_write_time = LastWriteTime(file);
+ }
+ return !ec && new_write_time.tv_sec > max_ts.tv_sec - 1;
+}();
+
+static const bool SupportsMinTime = [] {
+ using namespace std::chrono;
+ TimeSpec min_ts = {};
+ if (!ConvertToTimeSpec(min_ts, file_time_type::min()))
+ return false;
+ std::error_code ec;
+ TimeSpec old_write_time, new_write_time;
+ { // WARNING: Do not assert in this scope.
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ old_write_time = LastWriteTime(file);
+ file_time_type tp = file_time_type::min();
+ fs::last_write_time(file, tp, ec);
+ new_write_time = LastWriteTime(file);
+ }
+ return !ec && new_write_time.tv_sec < min_ts.tv_sec + 1;
+}();
+
+static const bool SupportsNanosecondRoundTrip = [] {
+ NanoSec ns(3);
+ static_assert(std::is_same<file_time_type::period, std::nano>::value, "");
+
+ // Test that the system call we use to set the times also supports nanosecond
+ // resolution. (utimes does not)
+ file_time_type ft(ns);
+ {
+ scoped_test_env env;
+ const path p = env.create_file("file", 42);
+ last_write_time(p, ft);
+ return last_write_time(p) == ft;
+ }
+}();
+
+// The HFS+ filesystem (used by default before macOS 10.13) stores timestamps at
+// a 1-second granularity, and APFS (now the default) at a 1 nanosecond granularity.
+// 1-second granularity is also the norm on many of the supported filesystems
+// on Linux as well.
+static const bool WorkaroundStatTruncatesToSeconds = [] {
+ MicroSec micros(3);
+ static_assert(std::is_same<file_time_type::period, std::nano>::value, "");
+
+ file_time_type ft(micros);
+ {
+ scoped_test_env env;
+ const path p = env.create_file("file", 42);
+ if (LastWriteTime(p).tv_nsec != 0)
+ return false;
+ last_write_time(p, ft);
+ return last_write_time(p) != ft && LastWriteTime(p).tv_nsec == 0;
+ }
+}();
+
+static const bool SupportsMinRoundTrip = [] {
+ TimeSpec ts = {};
+ if (!ConvertToTimeSpec(ts, file_time_type::min()))
+ return false;
+ file_time_type min_val = {};
+ if (!ConvertFromTimeSpec(min_val, ts))
+ return false;
+ return min_val == file_time_type::min();
+}();
+
+} // end namespace
+
+static bool CompareTime(TimeSpec t1, TimeSpec t2) {
+ if (SupportsNanosecondRoundTrip)
+ return CompareTimeExact(t1, t2);
+ if (t1.tv_sec != t2.tv_sec)
+ return false;
+
+ auto diff = std::abs(t1.tv_nsec - t2.tv_nsec);
+ if (WorkaroundStatTruncatesToSeconds)
+ return diff < duration_cast<NanoSec>(Sec(1)).count();
+ return diff < duration_cast<NanoSec>(MicroSec(1)).count();
+}
+
+static bool CompareTime(file_time_type t1, TimeSpec t2) {
+ TimeSpec ts1 = {};
+ if (!ConvertToTimeSpec(ts1, t1))
+ return false;
+ return CompareTime(ts1, t2);
+}
+
+static bool CompareTime(TimeSpec t1, file_time_type t2) {
+ return CompareTime(t2, t1);
+}
+
+static bool CompareTime(file_time_type t1, file_time_type t2) {
+ auto min_secs = duration_cast<Sec>(file_time_type::min().time_since_epoch());
+ bool IsMin =
+ t1.time_since_epoch() < min_secs || t2.time_since_epoch() < min_secs;
+
+ if (SupportsNanosecondRoundTrip && (!IsMin || SupportsMinRoundTrip))
+ return t1 == t2;
+ if (IsMin) {
+ return duration_cast<Sec>(t1.time_since_epoch()) ==
+ duration_cast<Sec>(t2.time_since_epoch());
+ }
+ file_time_type::duration dur;
+ if (t1 > t2)
+ dur = t1 - t2;
+ else
+ dur = t2 - t1;
+ if (WorkaroundStatTruncatesToSeconds)
+ return duration_cast<Sec>(dur).count() == 0;
+ return duration_cast<MicroSec>(dur).count() == 0;
+}
+
+// Check if a time point is representable on a given filesystem. Check that:
+// (A) 'tp' is representable as a time_t
+// (B) 'tp' is non-negative or the filesystem supports negative times.
+// (C) 'tp' is not 'file_time_type::max()' or the filesystem supports the max
+// value.
+// (D) 'tp' is not 'file_time_type::min()' or the filesystem supports the min
+// value.
+inline bool TimeIsRepresentableByFilesystem(file_time_type tp) {
+ TimeSpec ts = {};
+ if (!ConvertToTimeSpec(ts, tp))
+ return false;
+ else if (tp.time_since_epoch().count() < 0 && !SupportsNegativeTimes)
+ return false;
+ else if (tp == file_time_type::max() && !SupportsMaxTime)
+ return false;
+ else if (tp == file_time_type::min() && !SupportsMinTime)
+ return false;
+ return true;
+}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+// Create a sub-second duration using the smallest period the filesystem supports.
+file_time_type::duration SubSec(long long val) {
+ using SubSecT = file_time_type::duration;
+ if (SupportsNanosecondRoundTrip) {
+ return duration_cast<SubSecT>(NanoSec(val));
+ } else {
+ return duration_cast<SubSecT>(MicroSec(val));
+ }
+}
+
+TEST_SUITE(last_write_time_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const file_time_type t;
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(last_write_time(p)), file_time_type);
+ ASSERT_SAME_TYPE(decltype(last_write_time(p, ec)), file_time_type);
+ ASSERT_SAME_TYPE(decltype(last_write_time(p, t)), void);
+ ASSERT_SAME_TYPE(decltype(last_write_time(p, t, ec)), void);
+ ASSERT_NOT_NOEXCEPT(last_write_time(p));
+ ASSERT_NOT_NOEXCEPT(last_write_time(p, t));
+ ASSERT_NOEXCEPT(last_write_time(p, ec));
+ ASSERT_NOEXCEPT(last_write_time(p, t, ec));
+}
+
+TEST_CASE(read_last_write_time_static_env_test)
+{
+ using C = file_time_type::clock;
+ file_time_type min = file_time_type::min();
+ {
+ file_time_type ret = last_write_time(StaticEnv::File);
+ TEST_CHECK(ret != min);
+ TEST_CHECK(ret < C::now());
+ TEST_CHECK(CompareTime(ret, LastWriteTime(StaticEnv::File)));
+
+ file_time_type ret2 = last_write_time(StaticEnv::SymlinkToFile);
+ TEST_CHECK(CompareTime(ret, ret2));
+ TEST_CHECK(CompareTime(ret2, LastWriteTime(StaticEnv::SymlinkToFile)));
+ }
+ {
+ file_time_type ret = last_write_time(StaticEnv::Dir);
+ TEST_CHECK(ret != min);
+ TEST_CHECK(ret < C::now());
+ TEST_CHECK(CompareTime(ret, LastWriteTime(StaticEnv::Dir)));
+
+ file_time_type ret2 = last_write_time(StaticEnv::SymlinkToDir);
+ TEST_CHECK(CompareTime(ret, ret2));
+ TEST_CHECK(CompareTime(ret2, LastWriteTime(StaticEnv::SymlinkToDir)));
+ }
+}
+
+TEST_CASE(get_last_write_time_dynamic_env_test)
+{
+ using Clock = file_time_type::clock;
+ using Sec = std::chrono::seconds;
+ scoped_test_env env;
+
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+
+ const auto file_times = GetTimes(file);
+ const TimeSpec file_write_time = file_times.write;
+ const auto dir_times = GetTimes(dir);
+ const TimeSpec dir_write_time = dir_times.write;
+
+ file_time_type ftime = last_write_time(file);
+ TEST_CHECK(Clock::to_time_t(ftime) == file_write_time.tv_sec);
+ TEST_CHECK(CompareTime(ftime, file_write_time));
+
+ file_time_type dtime = last_write_time(dir);
+ TEST_CHECK(Clock::to_time_t(dtime) == dir_write_time.tv_sec);
+ TEST_CHECK(CompareTime(dtime, dir_write_time));
+
+ SleepFor(Sec(2));
+
+ // update file and add a file to the directory. Make sure the times increase.
+ std::ofstream of(file, std::ofstream::app);
+ of << "hello";
+ of.close();
+ env.create_file("dir/file1", 1);
+
+ file_time_type ftime2 = last_write_time(file);
+ file_time_type dtime2 = last_write_time(dir);
+
+ TEST_CHECK(ftime2 > ftime);
+ TEST_CHECK(dtime2 > dtime);
+ TEST_CHECK(CompareTime(LastWriteTime(file), ftime2));
+ TEST_CHECK(CompareTime(LastWriteTime(dir), dtime2));
+}
+
+
+TEST_CASE(set_last_write_time_dynamic_env_test)
+{
+ using Clock = file_time_type::clock;
+ scoped_test_env env;
+
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+ const auto now = Clock::now();
+ const file_time_type epoch_time = now - now.time_since_epoch();
+
+ const file_time_type future_time = now + Hours(3) + Sec(42) + SubSec(17);
+ const file_time_type past_time = now - Minutes(3) - Sec(42) - SubSec(17);
+ const file_time_type before_epoch_time =
+ epoch_time - Minutes(3) - Sec(42) - SubSec(17);
+ // FreeBSD has a bug in their utimes implementation where the time is not update
+ // when the number of seconds is '-1'.
+#if defined(__FreeBSD__)
+ const file_time_type just_before_epoch_time =
+ epoch_time - Sec(2) - SubSec(17);
+#else
+ const file_time_type just_before_epoch_time = epoch_time - SubSec(17);
+#endif
+
+ struct TestCase {
+ const char * case_name;
+ path p;
+ file_time_type new_time;
+ } cases[] = {
+ {"file, epoch_time", file, epoch_time},
+ {"dir, epoch_time", dir, epoch_time},
+ {"file, future_time", file, future_time},
+ {"dir, future_time", dir, future_time},
+ {"file, past_time", file, past_time},
+ {"dir, past_time", dir, past_time},
+ {"file, before_epoch_time", file, before_epoch_time},
+ {"dir, before_epoch_time", dir, before_epoch_time},
+ {"file, just_before_epoch_time", file, just_before_epoch_time},
+ {"dir, just_before_epoch_time", dir, just_before_epoch_time}
+ };
+ for (const auto& TC : cases) {
+ std::cerr << "Test Case = " << TC.case_name << "\n";
+ const auto old_times = GetTimes(TC.p);
+ file_time_type old_time;
+ TEST_REQUIRE(ConvertFromTimeSpec(old_time, old_times.write));
+
+ std::error_code ec = GetTestEC();
+ last_write_time(TC.p, TC.new_time, ec);
+ TEST_CHECK(!ec);
+
+ ec = GetTestEC();
+ file_time_type got_time = last_write_time(TC.p, ec);
+ TEST_REQUIRE(!ec);
+
+ if (TimeIsRepresentableByFilesystem(TC.new_time)) {
+ TEST_CHECK(got_time != old_time);
+ TEST_CHECK(CompareTime(got_time, TC.new_time));
+ TEST_CHECK(CompareTime(LastAccessTime(TC.p), old_times.access));
+ }
+ }
+}
+
+TEST_CASE(last_write_time_symlink_test)
+{
+ using Clock = file_time_type::clock;
+
+ scoped_test_env env;
+
+ const path file = env.create_file("file", 42);
+ const path sym = env.create_symlink("file", "sym");
+
+ const file_time_type new_time = Clock::now() + Hours(3);
+
+ const auto old_times = GetTimes(sym);
+ const auto old_sym_times = GetSymlinkTimes(sym);
+
+ std::error_code ec = GetTestEC();
+ last_write_time(sym, new_time, ec);
+ TEST_CHECK(!ec);
+
+ file_time_type got_time = last_write_time(sym);
+ TEST_CHECK(!CompareTime(got_time, old_times.write));
+ if (!WorkaroundStatTruncatesToSeconds) {
+ TEST_CHECK(got_time == new_time);
+ } else {
+ TEST_CHECK(CompareTime(got_time, new_time));
+ }
+
+ TEST_CHECK(CompareTime(LastWriteTime(file), new_time));
+ TEST_CHECK(CompareTime(LastAccessTime(sym), old_times.access));
+ std::pair<TimeSpec, TimeSpec> sym_times = GetSymlinkTimes(sym);
+ TEST_CHECK(CompareTime(sym_times.first, old_sym_times.first));
+ TEST_CHECK(CompareTime(sym_times.second, old_sym_times.second));
+}
+
+
+TEST_CASE(test_write_min_time)
+{
+ using Clock = file_time_type::clock;
+ scoped_test_env env;
+ const path p = env.create_file("file", 42);
+ const file_time_type old_time = last_write_time(p);
+ file_time_type new_time = file_time_type::min();
+
+ std::error_code ec = GetTestEC();
+ last_write_time(p, new_time, ec);
+ file_time_type tt = last_write_time(p);
+
+ if (TimeIsRepresentableByFilesystem(new_time)) {
+ TEST_CHECK(!ec);
+ TEST_CHECK(CompareTime(tt, new_time));
+
+ last_write_time(p, old_time);
+ new_time = file_time_type::min() + SubSec(1);
+
+ ec = GetTestEC();
+ last_write_time(p, new_time, ec);
+ tt = last_write_time(p);
+
+ if (TimeIsRepresentableByFilesystem(new_time)) {
+ TEST_CHECK(!ec);
+ TEST_CHECK(CompareTime(tt, new_time));
+ } else {
+ TEST_CHECK(ErrorIs(ec, std::errc::value_too_large));
+ TEST_CHECK(tt == old_time);
+ }
+ } else {
+ TEST_CHECK(ErrorIs(ec, std::errc::value_too_large));
+ TEST_CHECK(tt == old_time);
+ }
+}
+
+TEST_CASE(test_write_max_time) {
+ using Clock = file_time_type::clock;
+ using Sec = std::chrono::seconds;
+ using Hours = std::chrono::hours;
+
+ scoped_test_env env;
+ const path p = env.create_file("file", 42);
+ const file_time_type old_time = last_write_time(p);
+ file_time_type new_time = file_time_type::max();
+
+ std::error_code ec = GetTestEC();
+ last_write_time(p, new_time, ec);
+ file_time_type tt = last_write_time(p);
+
+ if (TimeIsRepresentableByFilesystem(new_time)) {
+ TEST_CHECK(!ec);
+ TEST_CHECK(CompareTime(tt, new_time));
+ } else {
+ TEST_CHECK(ErrorIs(ec, std::errc::value_too_large));
+ TEST_CHECK(tt == old_time);
+ }
+}
+
+TEST_CASE(test_value_on_failure)
+{
+ const path p = StaticEnv::DNE;
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(last_write_time(p, ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
+}
+
+TEST_CASE(test_exists_fails)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ permissions(dir, perms::none);
+
+ std::error_code ec = GetTestEC();
+ TEST_CHECK(last_write_time(file, ec) == file_time_type::min());
+ TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
+
+ ExceptionChecker Checker(file, std::errc::permission_denied,
+ "last_write_time");
+ TEST_CHECK_THROW_RESULT(filesystem_error, Checker, last_write_time(file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void permissions(const path& p, perms prms,
+// perm_options opts = perm_options::replace);
+// void permissions(const path& p, perms prms, std::error_code& ec) noexcept;
+// void permissions(const path& p, perms prms, perm_options opts, std::error_code);
+
+
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+using PR = fs::perms;
+
+TEST_SUITE(filesystem_permissions_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ const perms pr{}; ((void)pr);
+ const perm_options opts{}; ((void)opts);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr));
+ ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr, opts));
+ ASSERT_NOEXCEPT(fs::permissions(p, pr, ec));
+ ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr, opts, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, fs::perms opts,
+ const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::permissions(f, opts);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == ""
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)opts); ((void)ec);
+ return true;
+#endif
+ };
+
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path dne_sym = env.create_symlink(dne, "dne_sym");
+ { // !exists
+ std::error_code ec = GetTestEC();
+ fs::permissions(dne, fs::perms{}, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(ec != GetTestEC());
+ TEST_CHECK(checkThrow(dne, fs::perms{}, ec));
+ }
+ {
+ std::error_code ec = GetTestEC();
+ fs::permissions(dne_sym, fs::perms{}, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(ec != GetTestEC());
+ TEST_CHECK(checkThrow(dne_sym, fs::perms{}, ec));
+ }
+}
+
+TEST_CASE(basic_permissions_test)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file1", 42);
+ const path dir = env.create_dir("dir1");
+ const path file_for_sym = env.create_file("file2", 42);
+ const path sym = env.create_symlink(file_for_sym, "sym");
+ const perm_options AP = perm_options::add;
+ const perm_options RP = perm_options::remove;
+ const perm_options NF = perm_options::nofollow;
+ struct TestCase {
+ path p;
+ perms set_perms;
+ perms expected;
+ perm_options opts;
+ TestCase(path xp, perms xperms, perms xexpect,
+ perm_options xopts = perm_options::replace)
+ : p(xp), set_perms(xperms), expected(xexpect), opts(xopts) {}
+ } cases[] = {
+ // test file
+ {file, perms::none, perms::none},
+ {file, perms::owner_all, perms::owner_all},
+ {file, perms::group_all, perms::owner_all | perms::group_all, AP},
+ {file, perms::group_all, perms::owner_all, RP},
+ // test directory
+ {dir, perms::none, perms::none},
+ {dir, perms::owner_all, perms::owner_all},
+ {dir, perms::group_all, perms::owner_all | perms::group_all, AP},
+ {dir, perms::group_all, perms::owner_all, RP},
+ // test symlink without symlink_nofollow
+ {sym, perms::none, perms::none},
+ {sym, perms::owner_all, perms::owner_all},
+ {sym, perms::group_all, perms::owner_all | perms::group_all, AP},
+ {sym, perms::group_all, perms::owner_all, RP},
+ // test non-symlink with symlink_nofollow. The last test on file/dir
+ // will have set their permissions to perms::owner_all
+ {file, perms::group_all, perms::owner_all | perms::group_all, AP | NF},
+ {dir, perms::group_all, perms::owner_all | perms::group_all, AP | NF}
+ };
+ for (auto const& TC : cases) {
+ TEST_CHECK(status(TC.p).permissions() != TC.expected);
+ {
+ std::error_code ec = GetTestEC();
+ permissions(TC.p, TC.set_perms, TC.opts, ec);
+ TEST_CHECK(!ec);
+ auto pp = status(TC.p).permissions();
+ TEST_CHECK(pp == TC.expected);
+ }
+ if (TC.opts == perm_options::replace) {
+ std::error_code ec = GetTestEC();
+ permissions(TC.p, TC.set_perms, ec);
+ TEST_CHECK(!ec);
+ auto pp = status(TC.p).permissions();
+ TEST_CHECK(pp == TC.expected);
+ }
+ }
+}
+
+TEST_CASE(test_no_resolve_symlink_on_symlink)
+{
+ scoped_test_env env;
+ const path file = env.create_file("file", 42);
+ const path sym = env.create_symlink(file, "sym");
+ const auto file_perms = status(file).permissions();
+
+ struct TestCase {
+ perms set_perms;
+ perms expected; // only expected on platform that support symlink perms.
+ perm_options opts = perm_options::replace;
+ TestCase(perms xperms, perms xexpect,
+ perm_options xopts = perm_options::replace)
+ : set_perms(xperms), expected(xexpect), opts(xopts) {}
+ } cases[] = {
+ {perms::owner_all, perms::owner_all},
+ {perms::group_all, perms::owner_all | perms::group_all, perm_options::add},
+ {perms::owner_all, perms::group_all, perm_options::remove},
+ };
+ for (auto const& TC : cases) {
+#if defined(__APPLE__) || defined(__FreeBSD__)
+ // On OS X symlink permissions are supported. We should get an empty
+ // error code and the expected permissions.
+ const auto expected_link_perms = TC.expected;
+ std::error_code expected_ec;
+#else
+ // On linux symlink permissions are not supported. The error code should
+ // be 'operation_not_supported' and the symlink permissions should be
+ // unchanged.
+ const auto expected_link_perms = symlink_status(sym).permissions();
+ std::error_code expected_ec = std::make_error_code(std::errc::operation_not_supported);
+#endif
+ std::error_code ec = GetTestEC();
+ permissions(sym, TC.set_perms, TC.opts | perm_options::nofollow, ec);
+ TEST_CHECK(ec == expected_ec);
+ TEST_CHECK(status(file).permissions() == file_perms);
+ TEST_CHECK(symlink_status(sym).permissions() == expected_link_perms);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// 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);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+static int count_path_elems(const fs::path& p) {
+ int count = 0;
+ for (auto& elem : p) {
+ if (elem != "/" && elem != "")
+ ++count;
+ }
+ return count;
+}
+
+TEST_SUITE(filesystem_proximate_path_test_suite)
+
+
+TEST_CASE(signature_test)
+{
+ using fs::path;
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(proximate(p));
+ ASSERT_NOT_NOEXCEPT(proximate(p, p));
+ ASSERT_NOT_NOEXCEPT(proximate(p, ec));
+ ASSERT_NOT_NOEXCEPT(proximate(p, p, ec));
+}
+
+TEST_CASE(basic_test) {
+ using fs::path;
+ const path cwd = fs::current_path();
+ const path parent_cwd = cwd.parent_path();
+ const path curdir = cwd.filename();
+ TEST_REQUIRE(!cwd.native().empty());
+ int cwd_depth = count_path_elems(cwd);
+ path dot_dot_to_root;
+ for (int i=0; i < cwd_depth; ++i)
+ dot_dot_to_root /= "..";
+ path relative_cwd = cwd.native().substr(1);
+ // clang-format off
+ struct {
+ std::string input;
+ std::string base;
+ std::string expect;
+ } TestCases[] = {
+ {"", "", "."},
+ {cwd, "a", ".."},
+ {parent_cwd, "a", "../.."},
+ {"a", cwd, "a"},
+ {"a", parent_cwd, "fs.op.proximate/a"},
+ {"/", "a", dot_dot_to_root / ".."},
+ {"/", "a/b", dot_dot_to_root / "../.."},
+ {"/", "a/b/", dot_dot_to_root / "../../.."},
+ {"a", "/", relative_cwd / "a"},
+ {"a/b", "/", relative_cwd / "a/b"},
+ {"a", "/net", ".." / relative_cwd / "a"},
+ {"//foo/", "//foo", "/foo/"},
+ {"//foo", "//foo/", ".."},
+ {"//foo", "//foo", "."},
+ {"//foo/", "//foo/", "."},
+ {"//base", "a", dot_dot_to_root / "../base"},
+ {"a", "a", "."},
+ {"a/b", "a/b", "."},
+ {"a/b/c/", "a/b/c/", "."},
+ {"//foo/a/b", "//foo/a/b", "."},
+ {"/a/d", "/a/b/c", "../../d"},
+ {"/a/b/c", "/a/d", "../b/c"},
+ {"a/b/c", "a", "b/c"},
+ {"a/b/c", "a/b/c/x/y", "../.."},
+ {"a/b/c", "a/b/c", "."},
+ {"a/b", "c/d", "../../a/b"}
+ };
+ // clang-format on
+ int ID = 0;
+ for (auto& TC : TestCases) {
+ ++ID;
+ std::error_code ec = GetTestEC();
+ fs::path p(TC.input);
+ const fs::path output = fs::proximate(p, TC.base, ec);
+ if (ec) {
+ TEST_CHECK(!ec);
+ std::cerr << "TEST CASE #" << ID << " FAILED: \n";
+ std::cerr << " Input: '" << TC.input << "'\n";
+ std::cerr << " Base: '" << TC.base << "'\n";
+ std::cerr << " Expected: '" << TC.expect << "'\n";
+
+ std::cerr << std::endl;
+ } else if (!PathEq(output, TC.expect)) {
+ TEST_CHECK(PathEq(output, TC.expect));
+
+ const path canon_input = fs::weakly_canonical(TC.input);
+ const path canon_base = fs::weakly_canonical(TC.base);
+ const path lexically_p = canon_input.lexically_proximate(canon_base);
+ std::cerr << "TEST CASE #" << ID << " FAILED: \n";
+ std::cerr << " Input: '" << TC.input << "'\n";
+ std::cerr << " Base: '" << TC.base << "'\n";
+ std::cerr << " Expected: '" << TC.expect << "'\n";
+ std::cerr << " Output: '" << output.native() << "'\n";
+ std::cerr << " Lex Prox: '" << lexically_p.native() << "'\n";
+ std::cerr << " Canon Input: " << canon_input << "\n";
+ std::cerr << " Canon Base: " << canon_base << "\n";
+
+ std::cerr << std::endl;
+ }
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path read_symlink(const path& p);
+// path read_symlink(const path& p, error_code& ec);
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_read_symlink_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::read_symlink(p)), fs::path);
+ ASSERT_SAME_TYPE(decltype(fs::read_symlink(p, ec)), fs::path);
+
+ ASSERT_NOT_NOEXCEPT(fs::read_symlink(p));
+ // Not noexcept because of narrow contract
+ ASSERT_NOT_NOEXCEPT(fs::read_symlink(p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::read_symlink(f);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == ""
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)ec);
+ return true;
+#endif
+ };
+
+ scoped_test_env env;
+ const path cases[] = {
+ env.make_env_path("dne"),
+ env.create_file("file", 42),
+ env.create_dir("dir")
+ };
+ for (path const& p : cases) {
+ std::error_code ec;
+ const path ret = fs::read_symlink(p, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(ret == path{});
+ TEST_CHECK(checkThrow(p, ec));
+ }
+
+}
+
+TEST_CASE(basic_symlink_test)
+{
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path file = env.create_file("file", 42);
+ const path dir = env.create_dir("dir");
+ const path link = env.create_symlink(dne, "link");
+ const path nested_link = env.make_env_path("nested_link");
+ create_symlink(link, nested_link);
+ struct TestCase {
+ path symlink;
+ path expected;
+ } testCases[] = {
+ {env.create_symlink(dne, "dne_link"), dne},
+ {env.create_symlink(file, "file_link"), file},
+ {env.create_symlink(dir, "dir_link"), dir},
+ {nested_link, link}
+ };
+ for (auto& TC : testCases) {
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ const path ret = read_symlink(TC.symlink, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ret == TC.expected);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// 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);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+TEST_SUITE(filesystem_proximate_path_test_suite)
+
+TEST_CASE(test_signature) {
+
+}
+int main() {
+ // clang-format off
+ struct {
+ std::string input;
+ std::string expect;
+ } TestCases[] = {
+ {"", fs::current_path()},
+ {".", fs::current_path()},
+ {StaticEnv::File, StaticEnv::File},
+ {StaticEnv::Dir, StaticEnv::Dir},
+ {StaticEnv::SymlinkToDir, StaticEnv::Dir},
+ {StaticEnv::SymlinkToDir / "dir2/.", StaticEnv::Dir / "dir2"},
+ // FIXME? If the trailing separator occurs in a part of the path that exists,
+ // it is ommitted. Otherwise it is added to the end of the result.
+ {StaticEnv::SymlinkToDir / "dir2/./", StaticEnv::Dir / "dir2"},
+ {StaticEnv::SymlinkToDir / "dir2/DNE/./", StaticEnv::Dir / "dir2/DNE/"},
+ {StaticEnv::SymlinkToDir / "dir2", StaticEnv::Dir2},
+ {StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/..", StaticEnv::Dir2 / ""},
+ {StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2", StaticEnv::Dir2 / "DNE/DNE2"},
+ {StaticEnv::Dir / "../dir1", StaticEnv::Dir},
+ {StaticEnv::Dir / "./.", StaticEnv::Dir},
+ {StaticEnv::Dir / "DNE/../foo", StaticEnv::Dir / "foo"}
+ };
+ // clang-format on
+ int ID = 0;
+ bool Failed = false;
+ for (auto& TC : TestCases) {
+ ++ID;
+ fs::path p(TC.input);
+ const fs::path output = fs::weakly_canonical(p);
+ if (output != TC.expect) {
+ Failed = true;
+ std::cerr << "TEST CASE #" << ID << " FAILED: \n";
+ std::cerr << " Input: '" << TC.input << "'\n";
+ std::cerr << " Expected: '" << TC.expect << "'\n";
+ std::cerr << " Output: '" << output.native() << "'";
+ std::cerr << std::endl;
+ }
+ }
+ return Failed;
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool remove(const path& p);
+// bool remove(const path& p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_remove_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::remove(p)), bool);
+ ASSERT_SAME_TYPE(decltype(fs::remove(p, ec)), bool);
+
+ ASSERT_NOT_NOEXCEPT(fs::remove(p));
+ ASSERT_NOEXCEPT(fs::remove(p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::remove(f);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == ""
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)ec);
+ return true;
+#endif
+ };
+ scoped_test_env env;
+ const path non_empty_dir = env.create_dir("dir");
+ env.create_file(non_empty_dir / "file1", 42);
+ const path bad_perms_dir = env.create_dir("bad_dir");
+ const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42);
+ permissions(bad_perms_dir, perms::none);
+ const path testCases[] = {
+ non_empty_dir,
+ file_in_bad_dir,
+ };
+ for (auto& p : testCases) {
+ std::error_code ec;
+
+ TEST_CHECK(!fs::remove(p, ec));
+ TEST_CHECK(ec);
+ TEST_CHECK(checkThrow(p, ec));
+ }
+
+ // PR#35780
+ const path testCasesNonexistant[] = {
+ "",
+ env.make_env_path("dne")
+ };
+
+ for (auto& p : testCasesNonexistant) {
+ std::error_code ec;
+
+ TEST_CHECK(!fs::remove(p, ec));
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(basic_remove_test)
+{
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path link = env.create_symlink(dne, "link");
+ const path nested_link = env.make_env_path("nested_link");
+ create_symlink(link, nested_link);
+ const path testCases[] = {
+ env.create_file("file", 42),
+ env.create_dir("empty_dir"),
+ nested_link,
+ link
+ };
+ for (auto& p : testCases) {
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ TEST_CHECK(remove(p, ec));
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(symlink_status(p)));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// uintmax_t remove_all(const path& p);
+// uintmax_t remove_all(const path& p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_remove_all_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::remove_all(p)), std::uintmax_t);
+ ASSERT_SAME_TYPE(decltype(fs::remove_all(p, ec)), std::uintmax_t);
+
+ ASSERT_NOT_NOEXCEPT(fs::remove_all(p));
+ ASSERT_NOT_NOEXCEPT(fs::remove_all(p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::remove_all(f);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == ""
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)ec);
+ return true;
+#endif
+ };
+ scoped_test_env env;
+ const path non_empty_dir = env.create_dir("dir");
+ env.create_file(non_empty_dir / "file1", 42);
+ const path bad_perms_dir = env.create_dir("bad_dir");
+ const path file_in_bad_dir = env.create_file(bad_perms_dir / "file", 42);
+ permissions(bad_perms_dir, perms::none);
+ const path bad_perms_file = env.create_file("file2", 42);
+ permissions(bad_perms_file, perms::none);
+
+ const path testCases[] = {
+ file_in_bad_dir
+ };
+ const auto BadRet = static_cast<std::uintmax_t>(-1);
+ for (auto& p : testCases) {
+ std::error_code ec;
+
+ TEST_CHECK(fs::remove_all(p, ec) == BadRet);
+ TEST_CHECK(ec);
+ TEST_CHECK(checkThrow(p, ec));
+ }
+
+ // PR#35780
+ const path testCasesNonexistant[] = {
+ "",
+ env.make_env_path("dne")
+ };
+ for (auto &p : testCasesNonexistant) {
+ std::error_code ec;
+
+ TEST_CHECK(fs::remove_all(p, ec) == 0);
+ TEST_CHECK(!ec);
+ }
+}
+
+TEST_CASE(basic_remove_all_test)
+{
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path link = env.create_symlink(dne, "link");
+ const path nested_link = env.make_env_path("nested_link");
+ create_symlink(link, nested_link);
+ const path testCases[] = {
+ env.create_file("file", 42),
+ env.create_dir("empty_dir"),
+ nested_link,
+ link
+ };
+ for (auto& p : testCases) {
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ TEST_CHECK(remove(p, ec));
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(symlink_status(p)));
+ }
+}
+
+TEST_CASE(symlink_to_dir)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file(dir / "file", 42);
+ const path link = env.create_symlink(dir, "sym");
+
+ {
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ TEST_CHECK(remove_all(link, ec) == 1);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(symlink_status(link)));
+ TEST_CHECK(exists(dir));
+ TEST_CHECK(exists(file));
+ }
+}
+
+
+TEST_CASE(nested_dir)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path dir1 = env.create_dir(dir / "dir1");
+ const path out_of_dir_file = env.create_file("file1", 42);
+ const path all_files[] = {
+ dir, dir1,
+ env.create_file(dir / "file1", 42),
+ env.create_symlink(out_of_dir_file, dir / "sym1"),
+ env.create_file(dir1 / "file2", 42),
+ env.create_symlink(dir, dir1 / "sym2")
+ };
+ const std::size_t expected_count = sizeof(all_files) / sizeof(all_files[0]);
+
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ TEST_CHECK(remove_all(dir, ec) == expected_count);
+ TEST_CHECK(!ec);
+ for (auto const& p : all_files) {
+ TEST_CHECK(!exists(symlink_status(p)));
+ }
+ TEST_CHECK(exists(out_of_dir_file));
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void rename(const path& old_p, const path& new_p);
+// void rename(const path& old_p, const path& new_p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_rename_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(fs::rename(p, p)), void);
+ ASSERT_SAME_TYPE(decltype(fs::rename(p, p, ec)), void);
+
+ ASSERT_NOT_NOEXCEPT(fs::rename(p, p));
+ ASSERT_NOEXCEPT(fs::rename(p, p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, path const& t, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::rename(f, t);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == t
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)t); ((void)ec);
+ return true;
+#endif
+ };
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path file = env.create_file("file1", 42);
+ const path dir = env.create_dir("dir1");
+ struct TestCase {
+ path from;
+ path to;
+ } cases[] = {
+ {dne, dne},
+ {file, dir},
+ {dir, file}
+ };
+ for (auto& TC : cases) {
+ auto from_before = status(TC.from);
+ auto to_before = status(TC.to);
+ std::error_code ec;
+ rename(TC.from, TC.to, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(from_before.type() == status(TC.from).type());
+ TEST_CHECK(to_before.type() == status(TC.to).type());
+ TEST_CHECK(checkThrow(TC.from, TC.to, ec));
+ }
+}
+
+TEST_CASE(basic_rename_test)
+{
+ scoped_test_env env;
+
+ const std::error_code set_ec = std::make_error_code(std::errc::address_in_use);
+ const path file = env.create_file("file1", 42);
+ { // same file
+ std::error_code ec = set_ec;
+ rename(file, file, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(is_regular_file(file));
+ TEST_CHECK(file_size(file) == 42);
+ }
+ const path sym = env.create_symlink(file, "sym");
+ { // file -> symlink
+ std::error_code ec = set_ec;
+ rename(file, sym, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(file));
+ TEST_CHECK(is_regular_file(symlink_status(sym)));
+ TEST_CHECK(file_size(sym) == 42);
+ }
+ const path file2 = env.create_file("file2", 42);
+ const path file3 = env.create_file("file3", 100);
+ { // file -> file
+ std::error_code ec = set_ec;
+ rename(file2, file3, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(file2));
+ TEST_CHECK(is_regular_file(file3));
+ TEST_CHECK(file_size(file3) == 42);
+ }
+ const path dne = env.make_env_path("dne");
+ const path bad_sym = env.create_symlink(dne, "bad_sym");
+ const path bad_sym_dest = env.make_env_path("bad_sym2");
+ { // bad-symlink
+ std::error_code ec = set_ec;
+ rename(bad_sym, bad_sym_dest, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(!exists(symlink_status(bad_sym)));
+ TEST_CHECK(is_symlink(bad_sym_dest));
+ TEST_CHECK(read_symlink(bad_sym_dest) == dne);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// void resize_file(const path& p, uintmax_t new_size);
+// void resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_resize_file_test_suite)
+
+TEST_CASE(test_signatures)
+{
+ const path p; ((void)p);
+ std::uintmax_t i; ((void)i);
+ std::error_code ec; ((void)ec);
+
+ ASSERT_SAME_TYPE(decltype(fs::resize_file(p, i)), void);
+ ASSERT_SAME_TYPE(decltype(fs::resize_file(p, i, ec)), void);
+
+ ASSERT_NOT_NOEXCEPT(fs::resize_file(p, i));
+ ASSERT_NOEXCEPT(fs::resize_file(p, i, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, std::uintmax_t s, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ fs::resize_file(f, s);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == ""
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)s); ((void)ec);
+ return true;
+#endif
+ };
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path bad_sym = env.create_symlink(dne, "sym");
+ const path dir = env.create_dir("dir1");
+ const path cases[] = {
+ dne, bad_sym, dir
+ };
+ for (auto& p : cases) {
+ std::error_code ec;
+ resize_file(p, 42, ec);
+ TEST_REQUIRE(ec);
+ TEST_CHECK(checkThrow(p, 42, ec));
+ }
+}
+
+TEST_CASE(basic_resize_file_test)
+{
+ scoped_test_env env;
+ const path file1 = env.create_file("file1", 42);
+ const auto set_ec = std::make_error_code(std::errc::address_in_use);
+ { // grow file
+ const std::uintmax_t new_s = 100;
+ std::error_code ec = set_ec;
+ resize_file(file1, new_s, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(file1) == new_s);
+ }
+ { // shrink file
+ const std::uintmax_t new_s = 1;
+ std::error_code ec = set_ec;
+ resize_file(file1, new_s, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(file1) == new_s);
+ }
+ { // shrink file to zero
+ const std::uintmax_t new_s = 0;
+ std::error_code ec = set_ec;
+ resize_file(file1, new_s, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(file1) == new_s);
+ }
+ const path sym = env.create_symlink(file1, "sym");
+ { // grow file via symlink
+ const std::uintmax_t new_s = 1024;
+ std::error_code ec = set_ec;
+ resize_file(sym, new_s, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(file_size(file1) == new_s);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// space_info space(const path& p);
+// space_info space(const path& p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+#include <sys/statvfs.h>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+bool EqualDelta(std::uintmax_t x, std::uintmax_t y, std::uintmax_t delta) {
+ if (x >= y) {
+ return (x - y) <= delta;
+ } else {
+ return (y - x) <= delta;
+ }
+}
+
+TEST_SUITE(filesystem_space_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_SAME_TYPE(decltype(space(p)), space_info);
+ ASSERT_SAME_TYPE(decltype(space(p, ec)), space_info);
+ ASSERT_NOT_NOEXCEPT(space(p));
+ ASSERT_NOEXCEPT(space(p, ec));
+}
+
+TEST_CASE(test_error_reporting)
+{
+ auto checkThrow = [](path const& f, const std::error_code& ec)
+ {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ space(f);
+ return false;
+ } catch (filesystem_error const& err) {
+ return err.path1() == f
+ && err.path2() == ""
+ && err.code() == ec;
+ }
+#else
+ ((void)f); ((void)ec);
+ return true;
+#endif
+ };
+ const path cases[] = {
+ "",
+ StaticEnv::DNE,
+ StaticEnv::BadSymlink
+ };
+ for (auto& p : cases) {
+ const auto expect = static_cast<std::uintmax_t>(-1);
+ std::error_code ec;
+ space_info info = space(p, ec);
+ TEST_CHECK(ec);
+ TEST_CHECK(info.capacity == expect);
+ TEST_CHECK(info.free == expect);
+ TEST_CHECK(info.available == expect);
+ TEST_CHECK(checkThrow(p, ec));
+ }
+}
+
+TEST_CASE(basic_space_test)
+{
+ // All the test cases should reside on the same filesystem and therefore
+ // should have the same expected result. Compute this expected result
+ // one and check that it looks semi-sane.
+ struct statvfs expect;
+ TEST_REQUIRE(::statvfs(StaticEnv::Dir.c_str(), &expect) != -1);
+ TEST_CHECK(expect.f_bavail > 0);
+ TEST_CHECK(expect.f_bfree > 0);
+ TEST_CHECK(expect.f_bsize > 0);
+ TEST_CHECK(expect.f_blocks > 0);
+ TEST_REQUIRE(expect.f_frsize > 0);
+ auto do_mult = [&](std::uintmax_t val) {
+ std::uintmax_t fsize = expect.f_frsize;
+ std::uintmax_t new_val = val * fsize;
+ TEST_CHECK(new_val / fsize == val); // Test for overflow
+ return new_val;
+ };
+ const std::uintmax_t bad_value = static_cast<std::uintmax_t>(-1);
+ const std::uintmax_t expect_capacity = do_mult(expect.f_blocks);
+ const std::uintmax_t expect_free = do_mult(expect.f_bfree);
+ const std::uintmax_t expect_avail = do_mult(expect.f_bavail);
+
+ // Other processes running on the operating system may have changed
+ // the amount of space available. Check that these are within tolerances.
+ // Currently 5% of capacity
+ const std::uintmax_t delta = expect_capacity / 20;
+ const path cases[] = {
+ StaticEnv::File,
+ StaticEnv::Dir,
+ StaticEnv::Dir2,
+ StaticEnv::SymlinkToFile,
+ StaticEnv::SymlinkToDir
+ };
+ for (auto& p : cases) {
+ std::error_code ec = GetTestEC();
+ space_info info = space(p, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(info.capacity != bad_value);
+ TEST_CHECK(expect_capacity == info.capacity);
+ TEST_CHECK(info.free != bad_value);
+ TEST_CHECK(EqualDelta(expect_free, info.free, delta));
+ TEST_CHECK(info.available != bad_value);
+ TEST_CHECK(EqualDelta(expect_avail, info.available, delta));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// file_status status(const path& p);
+// file_status status(const path& p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_status_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(status(p));
+ ASSERT_NOEXCEPT(status(p, ec));
+}
+
+TEST_CASE(test_status_not_found)
+{
+ const std::error_code expect_ec =
+ std::make_error_code(std::errc::no_such_file_or_directory);
+ const path cases[] {
+ StaticEnv::DNE,
+ StaticEnv::BadSymlink
+ };
+ for (auto& p : cases) {
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ // test non-throwing overload.
+ file_status st = status(p, ec);
+ TEST_CHECK(ec == expect_ec);
+ TEST_CHECK(st.type() == file_type::not_found);
+ TEST_CHECK(st.permissions() == perms::unknown);
+ // test throwing overload. It should not throw even though it reports
+ // that the file was not found.
+ TEST_CHECK_NO_THROW(st = status(p));
+ TEST_CHECK(st.type() == file_type::not_found);
+ TEST_CHECK(st.permissions() == perms::unknown);
+ }
+}
+
+TEST_CASE(test_status_cannot_resolve)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file = env.create_file("dir/file", 42);
+ const path sym = env.create_symlink("dir/file", "sym");
+ permissions(dir, perms::none);
+
+ const std::error_code set_ec =
+ std::make_error_code(std::errc::address_in_use);
+ const std::error_code perm_ec =
+ std::make_error_code(std::errc::permission_denied);
+ const std::error_code name_too_long_ec =
+ std::make_error_code(std::errc::filename_too_long);
+
+ struct TestCase {
+ path p;
+ std::error_code expect_ec;
+ } const TestCases[] = {
+ {file, perm_ec},
+ {sym, perm_ec},
+ {path(std::string(2500, 'a')), name_too_long_ec}
+ };
+ for (auto& TC : TestCases)
+ {
+ { // test non-throwing case
+ std::error_code ec = set_ec;
+ file_status st = status(TC.p, ec);
+ TEST_CHECK(ec == TC.expect_ec);
+ TEST_CHECK(st.type() == file_type::none);
+ TEST_CHECK(st.permissions() == perms::unknown);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ { // test throwing case
+ try {
+ status(TC.p);
+ } catch (filesystem_error const& err) {
+ TEST_CHECK(err.path1() == TC.p);
+ TEST_CHECK(err.path2() == "");
+ TEST_CHECK(err.code() == TC.expect_ec);
+ }
+ }
+#endif
+ }
+}
+
+TEST_CASE(status_file_types_test)
+{
+ scoped_test_env env;
+ struct TestCase {
+ path p;
+ file_type expect_type;
+ } cases[] = {
+ {StaticEnv::File, file_type::regular},
+ {StaticEnv::SymlinkToFile, file_type::regular},
+ {StaticEnv::Dir, file_type::directory},
+ {StaticEnv::SymlinkToDir, file_type::directory},
+ // Block files tested elsewhere
+ {StaticEnv::CharFile, file_type::character},
+#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets
+ {env.create_socket("socket"), file_type::socket},
+#endif
+ {env.create_fifo("fifo"), file_type::fifo}
+ };
+ for (const auto& TC : cases) {
+ // test non-throwing case
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ file_status st = status(TC.p, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(st.type() == TC.expect_type);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ // test throwing case
+ TEST_REQUIRE_NO_THROW(st = status(TC.p));
+ TEST_CHECK(st.type() == TC.expect_type);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ }
+}
+
+TEST_CASE(test_block_file)
+{
+ const path possible_paths[] = {
+ "/dev/drive0", // Apple
+ "/dev/sda",
+ "/dev/loop0"
+ };
+ path p;
+ for (const path& possible_p : possible_paths) {
+ std::error_code ec;
+ if (exists(possible_p, ec)) {
+ p = possible_p;
+ break;
+ }
+ }
+ if (p == path{}) {
+ TEST_UNSUPPORTED();
+ }
+ // test non-throwing case
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ file_status st = status(p, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(st.type() == file_type::block);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ // test throwing case
+ TEST_REQUIRE_NO_THROW(st = status(p));
+ TEST_CHECK(st.type() == file_type::block);
+ TEST_CHECK(st.permissions() != perms::unknown);
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// bool status_known(file_status s) noexcept;
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(status_known_test_suite)
+
+TEST_CASE(signature_test)
+{
+ file_status s; ((void)s);
+ ASSERT_SAME_TYPE(decltype(status_known(s)), bool);
+ ASSERT_NOEXCEPT(status_known(s));
+}
+
+TEST_CASE(status_known_test)
+{
+ struct TestCase {
+ file_type type;
+ bool expect;
+ };
+ const TestCase testCases[] = {
+ {file_type::none, false},
+ {file_type::not_found, true},
+ {file_type::regular, true},
+ {file_type::directory, true},
+ {file_type::symlink, true},
+ {file_type::block, true},
+ {file_type::character, true},
+ {file_type::fifo, true},
+ {file_type::socket, true},
+ {file_type::unknown, true}
+ };
+ for (auto& TC : testCases) {
+ file_status s(TC.type);
+ TEST_CHECK(status_known(s) == TC.expect);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// file_status symlink_status(const path& p);
+// file_status symlink_status(const path& p, error_code& ec) noexcept;
+
+#include "filesystem_include.hpp"
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+TEST_SUITE(filesystem_symlink_status_test_suite)
+
+TEST_CASE(signature_test)
+{
+ const path p; ((void)p);
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(symlink_status(p));
+ ASSERT_NOEXCEPT(symlink_status(p, ec));
+}
+
+TEST_CASE(test_symlink_status_not_found)
+{
+ const std::error_code expect_ec =
+ std::make_error_code(std::errc::no_such_file_or_directory);
+ const path cases[] {
+ StaticEnv::DNE
+ };
+ for (auto& p : cases) {
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ // test non-throwing overload.
+ file_status st = symlink_status(p, ec);
+ TEST_CHECK(ec == expect_ec);
+ TEST_CHECK(st.type() == file_type::not_found);
+ TEST_CHECK(st.permissions() == perms::unknown);
+ // test throwing overload. It should not throw even though it reports
+ // that the file was not found.
+ TEST_CHECK_NO_THROW(st = status(p));
+ TEST_CHECK(st.type() == file_type::not_found);
+ TEST_CHECK(st.permissions() == perms::unknown);
+ }
+}
+
+TEST_CASE(test_symlink_status_cannot_resolve)
+{
+ scoped_test_env env;
+ const path dir = env.create_dir("dir");
+ const path file_in_dir = env.create_file("dir/file", 42);
+ const path sym_in_dir = env.create_symlink("dir/file", "dir/bad_sym");
+ const path sym_points_in_dir = env.create_symlink("dir/file", "sym");
+ permissions(dir, perms::none);
+
+ const std::error_code set_ec =
+ std::make_error_code(std::errc::address_in_use);
+ const std::error_code expect_ec =
+ std::make_error_code(std::errc::permission_denied);
+
+ const path fail_cases[] = {
+ file_in_dir, sym_in_dir
+ };
+ for (auto& p : fail_cases)
+ {
+ { // test non-throwing case
+ std::error_code ec = set_ec;
+ file_status st = symlink_status(p, ec);
+ TEST_CHECK(ec == expect_ec);
+ TEST_CHECK(st.type() == file_type::none);
+ TEST_CHECK(st.permissions() == perms::unknown);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ { // test throwing case
+ try {
+ symlink_status(p);
+ } catch (filesystem_error const& err) {
+ TEST_CHECK(err.path1() == p);
+ TEST_CHECK(err.path2() == "");
+ TEST_CHECK(err.code() == expect_ec);
+ }
+ }
+#endif
+ }
+ // Test that a symlink that points into a directory without read perms
+ // can be stat-ed using symlink_status
+ {
+ std::error_code ec = set_ec;
+ file_status st = symlink_status(sym_points_in_dir, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(st.type() == file_type::symlink);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ // test non-throwing version
+ TEST_REQUIRE_NO_THROW(st = symlink_status(sym_points_in_dir));
+ TEST_CHECK(st.type() == file_type::symlink);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ }
+}
+
+
+TEST_CASE(symlink_status_file_types_test)
+{
+ scoped_test_env env;
+ struct TestCase {
+ path p;
+ file_type expect_type;
+ } cases[] = {
+ {StaticEnv::BadSymlink, file_type::symlink},
+ {StaticEnv::File, file_type::regular},
+ {StaticEnv::SymlinkToFile, file_type::symlink},
+ {StaticEnv::Dir, file_type::directory},
+ {StaticEnv::SymlinkToDir, file_type::symlink},
+ // Block files tested elsewhere
+ {StaticEnv::CharFile, file_type::character},
+#if !defined(__APPLE__) && !defined(__FreeBSD__) // No support for domain sockets
+ {env.create_socket("socket"), file_type::socket},
+#endif
+ {env.create_fifo("fifo"), file_type::fifo}
+ };
+ for (const auto& TC : cases) {
+ // test non-throwing case
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ file_status st = symlink_status(TC.p, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(st.type() == TC.expect_type);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ // test throwing case
+ TEST_REQUIRE_NO_THROW(st = symlink_status(TC.p));
+ TEST_CHECK(st.type() == TC.expect_type);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ }
+}
+
+TEST_CASE(test_block_file)
+{
+ const path possible_paths[] = {
+ "/dev/drive0", // Apple
+ "/dev/sda", // Linux
+ "/dev/loop0" // Linux
+ // No FreeBSD files known
+ };
+ path p;
+ for (const path& possible_p : possible_paths) {
+ std::error_code ec;
+ if (exists(possible_p, ec)) {
+ p = possible_p;
+ break;
+ }
+ }
+ if (p == path{}) {
+ TEST_UNSUPPORTED();
+ }
+ scoped_test_env env;
+ { // test block file
+ // test non-throwing case
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ file_status st = symlink_status(p, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(st.type() == file_type::block);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ // test throwing case
+ TEST_REQUIRE_NO_THROW(st = symlink_status(p));
+ TEST_CHECK(st.type() == file_type::block);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ }
+ const path sym = env.make_env_path("sym");
+ create_symlink(p, sym);
+ { // test symlink to block file
+ // test non-throwing case
+ std::error_code ec = std::make_error_code(std::errc::address_in_use);
+ file_status st = symlink_status(sym, ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(st.type() == file_type::symlink);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ // test throwing case
+ TEST_REQUIRE_NO_THROW(st = symlink_status(sym));
+ TEST_CHECK(st.type() == file_type::symlink);
+ TEST_CHECK(st.permissions() != perms::unknown);
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path temp_directory_path();
+// path temp_directory_path(error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <memory>
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+#include "test_macros.h"
+#include "rapid-cxx-test.hpp"
+#include "filesystem_test_helper.hpp"
+
+using namespace fs;
+
+void PutEnv(std::string var, std::string value) {
+ assert(::setenv(var.c_str(), value.c_str(), /* overwrite */ 1) == 0);
+}
+
+void UnsetEnv(std::string var) {
+ assert(::unsetenv(var.c_str()) == 0);
+}
+
+TEST_SUITE(filesystem_temp_directory_path_test_suite)
+
+TEST_CASE(signature_test)
+{
+ std::error_code ec; ((void)ec);
+ ASSERT_NOT_NOEXCEPT(temp_directory_path());
+ ASSERT_NOT_NOEXCEPT(temp_directory_path(ec));
+}
+
+TEST_CASE(basic_tests)
+{
+ scoped_test_env env;
+ const path dne = env.make_env_path("dne");
+ const path file = env.create_file("file", 42);
+ const path dir_perms = env.create_dir("bad_perms_dir");
+ const path nested_dir = env.create_dir("bad_perms_dir/nested");
+ permissions(dir_perms, perms::none);
+ const std::error_code expect_ec = std::make_error_code(std::errc::not_a_directory);
+ struct TestCase {
+ std::string name;
+ path p;
+ } cases[] = {
+ {"TMPDIR", env.create_dir("dir1")},
+ {"TMP", env.create_dir("dir2")},
+ {"TEMP", env.create_dir("dir3")},
+ {"TEMPDIR", env.create_dir("dir4")}
+ };
+ for (auto& TC : cases) {
+ PutEnv(TC.name, TC.p);
+ }
+ for (auto& TC : cases) {
+ std::error_code ec = GetTestEC();
+ path ret = temp_directory_path(ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ret == TC.p);
+ TEST_CHECK(is_directory(ret));
+
+ // Set the env variable to a path that does not exist and check
+ // that it fails.
+ PutEnv(TC.name, dne);
+ ec = GetTestEC();
+ ret = temp_directory_path(ec);
+ LIBCPP_ONLY(TEST_CHECK(ec == expect_ec));
+ TEST_CHECK(ec != GetTestEC());
+ TEST_CHECK(ec);
+ TEST_CHECK(ret == "");
+
+ // Set the env variable to point to a file and check that it fails.
+ PutEnv(TC.name, file);
+ ec = GetTestEC();
+ ret = temp_directory_path(ec);
+ LIBCPP_ONLY(TEST_CHECK(ec == expect_ec));
+ TEST_CHECK(ec != GetTestEC());
+ TEST_CHECK(ec);
+ TEST_CHECK(ret == "");
+
+ // Set the env variable to point to a dir we can't access
+ PutEnv(TC.name, nested_dir);
+ ec = GetTestEC();
+ ret = temp_directory_path(ec);
+ TEST_CHECK(ec == std::make_error_code(std::errc::permission_denied));
+ TEST_CHECK(ret == "");
+
+ // Set the env variable to point to a non-existent dir
+ PutEnv(TC.name, TC.p / "does_not_exist");
+ ec = GetTestEC();
+ ret = temp_directory_path(ec);
+ TEST_CHECK(ec != GetTestEC());
+ TEST_CHECK(ec);
+ TEST_CHECK(ret == "");
+
+ // Finally erase this env variable
+ UnsetEnv(TC.name);
+ }
+ // No env variables are defined
+ {
+ std::error_code ec = GetTestEC();
+ path ret = temp_directory_path(ec);
+ TEST_CHECK(!ec);
+ TEST_CHECK(ret == "/tmp");
+ TEST_CHECK(is_directory(ret));
+ }
+}
+
+TEST_SUITE_END()
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+
+// <filesystem>
+
+// path weakly_canonical(const path& p);
+// path weakly_canonical(const path& p, error_code& ec);
+
+#include "filesystem_include.hpp"
+#include <type_traits>
+#include <vector>
+#include <iostream>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "count_new.hpp"
+#include "filesystem_test_helper.hpp"
+
+
+int main() {
+ // clang-format off
+ struct {
+ std::string input;
+ std::string expect;
+ } TestCases[] = {
+ {"", fs::current_path()},
+ {".", fs::current_path()},
+ {"/", "/"},
+ {"/foo", "/foo"},
+ {"/.", "/"},
+ {"/./", "/"},
+ {"a/b", fs::current_path() / "a/b"},
+ {"a", fs::current_path() / "a"},
+ {"a/b/", fs::current_path() / "a/b/"},
+ {StaticEnv::File, StaticEnv::File},
+ {StaticEnv::Dir, StaticEnv::Dir},
+ {StaticEnv::SymlinkToDir, StaticEnv::Dir},
+ {StaticEnv::SymlinkToDir / "dir2/.", StaticEnv::Dir / "dir2"},
+ // FIXME? If the trailing separator occurs in a part of the path that exists,
+ // it is ommitted. Otherwise it is added to the end of the result.
+ {StaticEnv::SymlinkToDir / "dir2/./", StaticEnv::Dir / "dir2"},
+ {StaticEnv::SymlinkToDir / "dir2/DNE/./", StaticEnv::Dir / "dir2/DNE/"},
+ {StaticEnv::SymlinkToDir / "dir2", StaticEnv::Dir2},
+ {StaticEnv::SymlinkToDir / "dir2/../dir2/DNE/..", StaticEnv::Dir2 / ""},
+ {StaticEnv::SymlinkToDir / "dir2/dir3/../DNE/DNE2", StaticEnv::Dir2 / "DNE/DNE2"},
+ {StaticEnv::Dir / "../dir1", StaticEnv::Dir},
+ {StaticEnv::Dir / "./.", StaticEnv::Dir},
+ {StaticEnv::Dir / "DNE/../foo", StaticEnv::Dir / "foo"}
+ };
+ // clang-format on
+ int ID = 0;
+ bool Failed = false;
+ for (auto& TC : TestCases) {
+ ++ID;
+ fs::path p(TC.input);
+ const fs::path output = fs::weakly_canonical(p);
+ if (!PathEq(output, TC.expect)) {
+ Failed = true;
+ std::cerr << "TEST CASE #" << ID << " FAILED: \n";
+ std::cerr << " Input: '" << TC.input << "'\n";
+ std::cerr << " Expected: '" << TC.expect << "'\n";
+ std::cerr << " Output: '" << output.native() << "'";
+ std::cerr << std::endl;
+ }
+ }
+ return Failed;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <filesystem>
+
+// #define __cpp_lib_filesystem 201703L
+
+#include <filesystem>
+#include "test_macros.h"
+
+#if TEST_STD_VER >= 17
+#ifndef __cpp_lib_filesystem
+#error Filesystem feature test macro is not defined (__cpp_lib_filesystem)
+#elif __cpp_lib_filesystem != 201703L
+#error Filesystem feature test macro has an incorrect value (__cpp_lib_filesystem)
+#endif
+#else // TEST_STD_VER < 17
+#ifdef __cpp_lib_filesystem
+#error Filesystem feature test macro should not be defined before C++17
+#endif
+#endif
+
+int main() { }
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: c++98 || c++03 || c++11 || c++14
+
+// <filesystem>
+
+// namespace std::filesystem
+
+#include <filesystem>
+#include "test_macros.h"
+
+using namespace std::filesystem;
+
+#if TEST_STD_VER >= 11
+// expected-error@-3 {{no namespace named 'filesystem' in namespace 'std';}}
+#else
+// expected-error@-5 {{expected namespace name}}
+#endif
+
+int main() {
+
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <filesystem>
+
+// namespace std::filesystem
+
+#include <filesystem>
+#include <type_traits>
+
+using namespace std::filesystem;
+
+int main() {
+ static_assert(std::is_same<
+ path,
+ std::filesystem::path
+ >::value, "");
+}
--- /dev/null
+# Disable all of the filesystem tests if the correct feature is not available.
+if 'c++filesystem' not in config.available_features:
+ config.unsupported = True
#ifndef TEST_SUPPORT_FILESYSTEM_INCLUDE_HPP
#define TEST_SUPPORT_FILESYSTEM_INCLUDE_HPP
-#include <ciso646>
-// Test against std::filesystem for STL's other than libc++
-#ifndef _LIBCPP_VERSION
-#define TEST_INCLUDE_STD_FILESYSTEM
-#endif
-
-#ifdef TEST_INCLUDE_STD_FILESYSTEM
#include <filesystem>
-namespace fs = std::filesystem;
+#include "test_macros.h"
+
+#if defined(_LIBCPP_VERSION) && TEST_STD_VER < 17
+namespace fs = std::__fs::filesystem;
#else
-#include <experimental/filesystem>
-namespace fs = std::experimental::filesystem;
+namespace fs = std::filesystem;
#endif
#endif
enable_fs = self.get_lit_bool('enable_filesystem', default=False)
if not enable_fs:
return
- enable_experimental = self.get_lit_bool('enable_experimental', default=False)
- if not enable_experimental:
- self.lit_config.fatal(
- 'filesystem is enabled but libc++experimental.a is not.')
self.config.available_features.add('c++filesystem')
static_env = os.path.join(self.libcxx_src_root, 'test', 'std',
- 'experimental', 'filesystem', 'Inputs', 'static_test_env')
+ 'input.output', 'filesystems', 'Inputs', 'static_test_env')
static_env = os.path.realpath(static_env)
assert os.path.isdir(static_env)
self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env]
if libcxx_experimental:
self.config.available_features.add('c++experimental')
self.cxx.link_flags += ['-lc++experimental']
+ libcxx_fs = self.get_lit_bool('enable_filesystem', default=False)
+ if libcxx_fs:
+ self.config.available_features.add('c++fs')
+ self.cxx.link_flags += ['-lc++fs']
if self.link_shared:
self.cxx.link_flags += ['-lc++']
else:
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td><a href="https://wg21.link/P0024R2">P0024R2</a></td><td>LWG</td><td>The Parallelism TS Should be Standardized</td><td>Jacksonville</td><td></td><td></td></tr>
<tr><td><a href="https://wg21.link/P0226R1">P0226R1</a></td><td>LWG</td><td>Mathematical Special Functions for C++17</td><td>Jacksonville</td><td></td><td></td></tr>
- <tr><td><a href="https://wg21.link/P0220R1">P0220R1</a></td><td>LWG</td><td>Adopt Library Fundamentals V1 TS Components for C++17</td><td>Jacksonville</td><td>In Progress</td><td></td></tr>
+ <tr><td><a href="https://wg21.link/P0220R1">P0220R1</a></td><td>LWG</td><td>Adopt Library Fundamentals V1 TS Components for C++17</td><td>Jacksonville</td><td>Complete</td><td>7.0</td></tr>
<tr><td><a href="https://wg21.link/P0218R1">P0218R1</a></td><td>LWG</td><td>Adopt the File System TS for C++17</td><td>Jacksonville</td><td>In Progress</td><td></td></tr>
<tr><td><a href="https://wg21.link/P0033R1">P0033R1</a></td><td>LWG</td><td>Re-enabling shared_from_this</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
<tr><td><a href="https://wg21.link/P0005R4">P0005R4</a></td><td>LWG</td><td>Adopt not_fn from Library Fundamentals 2 for C++17</td><td>Jacksonville</td><td>Complete</td><td>3.9</td></tr>
<tr><td><a href="https://wg21.link/LWG2778">2778</a></td><td>basic_string_view is missing constexpr</td><td>Issaquah</td><td>Complete</td></tr>
<tr><td></td><td></td><td></td><td></td></tr>
<tr><td><a href="https://wg21.link/LWG2260">2260</a></td><td>Missing requirement for Allocator::pointer</td><td>Kona</td><td></td></tr>
- <tr><td><a href="https://wg21.link/LWG2676">2676</a></td><td>Provide filesystem::path overloads for File-based streams</td><td>Kona</td><td></td></tr>
+ <tr><td><a href="https://wg21.link/LWG2676">2676</a></td><td>Provide filesystem::path overloads for File-based streams</td><td>Kona</td><td>Complete</td></tr>
<tr><td><a href="https://wg21.link/LWG2768">2768</a></td><td>any_cast and move semantics</td><td>Kona</td><td>Complete</td></tr>
<tr><td><a href="https://wg21.link/LWG2769">2769</a></td><td>Redundant const in the return type of any_cast(const any&)</td><td>Kona</td><td>Complete</td></tr>
<tr><td><a href="https://wg21.link/LWG2781">2781</a></td><td>Contradictory requirements for std::function and std::reference_wrapper</td><td>Kona</td><td>Complete</td></tr>