From 0ca7ba9aa6a0b5b2c71184cd1853446cec9a0889 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 30 Apr 2015 20:11:52 +0100 Subject: [PATCH] Implement N4100 File System TS * acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Define. (GLIBCXX_CHECK_FILESYSTEM_DEPS): Define. * config.h.in: Regenerate. * configure: Regenerate. * configure.ac: Enable filesystem TS and check its dependencies. * include/Makefile.am: Add new headers. * include/Makefile.in: Regenerate. * include/bits/locale_conv.h (__do_str_code_cvt, __str_codecvt_in, __str_codecvt_out): Move code conversion logic from wstring_convert into new global functions. (wstring_convert::to_bytes, wstring_convert::from_bytes): Use new functions. (wstring_convert::_M_conv): Remove. * include/bits/quoted_string.h (_Quoted_string): Split out of iomanip. * include/experimental/filesystem: New. * include/experimental/fs_dir.h: New. * include/experimental/fs_fwd.h: New. * include/experimental/fs_ops.h: New. * include/experimental/fs_path.h: New. * include/std/iomanip (_Quoted_string): Move to bits/quoted_string.h. * python/libstdcxx/v6/printers.py (StdExpPathPrinter): Add. * src/Makefile.am (SUBDIRS): Add filesystem. * src/Makefile.in: Regenerate. * src/filesystem/Makefile.am: New. * src/filesystem/Makefile.in: New. * src/filesystem/dir.cc: New. * src/filesystem/ops.cc: New. * src/filesystem/path.cc: New. * testsuite/experimental/filesystem/operations/absolute.cc: New. * testsuite/experimental/filesystem/operations/copy.cc: New. * testsuite/experimental/filesystem/operations/current_path.cc: New. * testsuite/experimental/filesystem/path/append/path.cc: New. * testsuite/experimental/filesystem/path/assign/assign.cc: New. * testsuite/experimental/filesystem/path/assign/copy.cc: New. * testsuite/experimental/filesystem/path/compare/compare.cc: New. * testsuite/experimental/filesystem/path/compare/path.cc: New. * testsuite/experimental/filesystem/path/compare/strings.cc: New. * testsuite/experimental/filesystem/path/concat/path.cc: New. * testsuite/experimental/filesystem/path/concat/strings.cc: New. * testsuite/experimental/filesystem/path/construct/copy.cc: New. * testsuite/experimental/filesystem/path/construct/default.cc: New. * testsuite/experimental/filesystem/path/construct/locale.cc: New. * testsuite/experimental/filesystem/path/construct/range.cc: New. * testsuite/experimental/filesystem/path/decompose/extension.cc: New. * testsuite/experimental/filesystem/path/decompose/filename.cc: New. * testsuite/experimental/filesystem/path/decompose/parent_path.cc: New. * testsuite/experimental/filesystem/path/decompose/relative_path.cc: New. * testsuite/experimental/filesystem/path/decompose/root_directory.cc: New. * testsuite/experimental/filesystem/path/decompose/root_name.cc: New. * testsuite/experimental/filesystem/path/decompose/root_path.cc: New. * testsuite/experimental/filesystem/path/decompose/stem.cc: New. * testsuite/experimental/filesystem/path/generic/generic_string.cc: New. * testsuite/experimental/filesystem/path/itr/traversal.cc: New. * testsuite/experimental/filesystem/path/modifiers/clear.cc: New. * testsuite/experimental/filesystem/path/modifiers/make_preferred.cc: New. * testsuite/experimental/filesystem/path/modifiers/remove_filename.cc: New. * testsuite/experimental/filesystem/path/modifiers/replace_extension.cc: New. * testsuite/experimental/filesystem/path/modifiers/replace_filename.cc: New. * testsuite/experimental/filesystem/path/modifiers/swap.cc: New. * testsuite/experimental/filesystem/path/nonmember/hash_value.cc: New. * testsuite/experimental/filesystem/path/query/empty.cc: New. * testsuite/experimental/filesystem/path/query/has_extension.cc: New. * testsuite/experimental/filesystem/path/query/has_filename.cc: New. * testsuite/experimental/filesystem/path/query/has_parent_path.cc: New. * testsuite/experimental/filesystem/path/query/has_relative_path.cc: New. * testsuite/experimental/filesystem/path/query/has_root_directory.cc: New. * testsuite/experimental/filesystem/path/query/has_root_name.cc: New. * testsuite/experimental/filesystem/path/query/has_root_path.cc: New. * testsuite/experimental/filesystem/path/query/has_stem.cc: New. * testsuite/experimental/filesystem/path/query/is_relative.cc: New. * testsuite/util/testsuite_fs.h: New. From-SVN: r222654 --- libstdc++-v3/ChangeLog | 90 ++ libstdc++-v3/acinclude.m4 | 95 +- libstdc++-v3/config.h.in | 34 + libstdc++-v3/configure | 562 +++++++- libstdc++-v3/configure.ac | 6 + libstdc++-v3/include/Makefile.am | 15 +- libstdc++-v3/include/Makefile.in | 12 +- libstdc++-v3/include/bits/locale_conv.h | 173 ++- libstdc++-v3/include/bits/quoted_string.h | 164 +++ libstdc++-v3/include/experimental/filesystem | 77 ++ libstdc++-v3/include/experimental/fs_dir.h | 326 +++++ libstdc++-v3/include/experimental/fs_fwd.h | 289 ++++ libstdc++-v3/include/experimental/fs_ops.h | 291 ++++ libstdc++-v3/include/experimental/fs_path.h | 1014 ++++++++++++++ libstdc++-v3/include/std/iomanip | 123 +- libstdc++-v3/python/libstdcxx/v6/printers.py | 21 + libstdc++-v3/scripts/testsuite_flags.in | 3 +- libstdc++-v3/src/Makefile.am | 11 +- libstdc++-v3/src/Makefile.in | 7 +- libstdc++-v3/src/filesystem/Makefile.am | 100 ++ libstdc++-v3/src/filesystem/Makefile.in | 661 ++++++++++ libstdc++-v3/src/filesystem/dir.cc | 396 ++++++ libstdc++-v3/src/filesystem/ops.cc | 1169 +++++++++++++++++ libstdc++-v3/src/filesystem/path.cc | 464 +++++++ .../filesystem/operations/absolute.cc | 55 + .../filesystem/operations/copy.cc | 55 + .../filesystem/operations/current_path.cc | 57 + .../filesystem/path/append/path.cc | 63 + .../filesystem/path/assign/assign.cc | 89 ++ .../filesystem/path/assign/copy.cc | 55 + .../filesystem/path/compare/compare.cc | 50 + .../filesystem/path/compare/path.cc | 50 + .../filesystem/path/compare/strings.cc | 48 + .../filesystem/path/concat/path.cc | 68 + .../filesystem/path/concat/strings.cc | 51 + .../filesystem/path/construct/copy.cc | 54 + .../filesystem/path/construct/default.cc | 50 + .../filesystem/path/construct/locale.cc | 39 + .../filesystem/path/construct/range.cc | 60 + .../filesystem/path/decompose/extension.cc | 61 + .../filesystem/path/decompose/filename.cc | 58 + .../filesystem/path/decompose/parent_path.cc | 61 + .../path/decompose/relative_path.cc | 65 + .../path/decompose/root_directory.cc | 60 + .../filesystem/path/decompose/root_name.cc | 42 + .../filesystem/path/decompose/root_path.cc | 55 + .../filesystem/path/decompose/stem.cc | 53 + .../filesystem/path/generic/generic_string.cc | 48 + .../filesystem/path/itr/traversal.cc | 86 ++ .../filesystem/path/modifiers/clear.cc | 45 + .../path/modifiers/make_preferred.cc | 63 + .../path/modifiers/remove_filename.cc | 53 + .../path/modifiers/replace_extension.cc | 52 + .../path/modifiers/replace_filename.cc | 52 + .../filesystem/path/modifiers/swap.cc | 44 + .../filesystem/path/nonmember/hash_value.cc | 51 + .../filesystem/path/query/empty.cc | 43 + .../filesystem/path/query/has_extension.cc | 43 + .../filesystem/path/query/has_filename.cc | 43 + .../filesystem/path/query/has_parent_path.cc | 43 + .../path/query/has_relative_path.cc | 43 + .../path/query/has_root_directory.cc | 43 + .../filesystem/path/query/has_root_name.cc | 43 + .../filesystem/path/query/has_root_path.cc | 43 + .../filesystem/path/query/has_stem.cc | 43 + .../filesystem/path/query/is_relative.cc | 43 + libstdc++-v3/testsuite/lib/dg-options.exp | 9 + libstdc++-v3/testsuite/lib/libstdc++.exp | 47 + libstdc++-v3/testsuite/util/testsuite_fs.h | 67 + 69 files changed, 8252 insertions(+), 197 deletions(-) create mode 100644 libstdc++-v3/include/bits/quoted_string.h create mode 100644 libstdc++-v3/include/experimental/filesystem create mode 100644 libstdc++-v3/include/experimental/fs_dir.h create mode 100644 libstdc++-v3/include/experimental/fs_fwd.h create mode 100644 libstdc++-v3/include/experimental/fs_ops.h create mode 100644 libstdc++-v3/include/experimental/fs_path.h create mode 100644 libstdc++-v3/src/filesystem/Makefile.am create mode 100644 libstdc++-v3/src/filesystem/Makefile.in create mode 100644 libstdc++-v3/src/filesystem/dir.cc create mode 100644 libstdc++-v3/src/filesystem/ops.cc create mode 100644 libstdc++-v3/src/filesystem/path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/append/path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/assign/copy.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/compare/compare.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/compare/path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/compare/strings.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/concat/path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/construct/copy.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/construct/default.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/construct/locale.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/extension.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/filename.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/parent_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/relative_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_directory.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_name.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/decompose/stem.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/itr/traversal.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/clear.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/make_preferred.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/remove_filename.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_extension.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_filename.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/swap.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/nonmember/hash_value.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/empty.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_extension.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_filename.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_parent_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_relative_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_directory.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_name.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_path.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/has_stem.cc create mode 100644 libstdc++-v3/testsuite/experimental/filesystem/path/query/is_relative.cc create mode 100644 libstdc++-v3/testsuite/util/testsuite_fs.h diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 28f1b8b1474..34e731a347c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,93 @@ +2015-04-30 Jonathan Wakely + + Implement N4100 File System TS + * acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Define. + (GLIBCXX_CHECK_FILESYSTEM_DEPS): Define. + * config.h.in: Regenerate. + * configure: Regenerate. + * configure.ac: Enable filesystem TS and check its dependencies. + * include/Makefile.am: Add new headers. + * include/Makefile.in: Regenerate. + * include/bits/locale_conv.h (__do_str_code_cvt, __str_codecvt_in, + __str_codecvt_out): Move code conversion logic from wstring_convert + into new global functions. + (wstring_convert::to_bytes, wstring_convert::from_bytes): Use new + functions. + (wstring_convert::_M_conv): Remove. + * include/bits/quoted_string.h (_Quoted_string): Split out of iomanip. + * include/experimental/filesystem: New. + * include/experimental/fs_dir.h: New. + * include/experimental/fs_fwd.h: New. + * include/experimental/fs_ops.h: New. + * include/experimental/fs_path.h: New. + * include/std/iomanip (_Quoted_string): Move to bits/quoted_string.h. + * python/libstdcxx/v6/printers.py (StdExpPathPrinter): Add. + * src/Makefile.am (SUBDIRS): Add filesystem. + * src/Makefile.in: Regenerate. + * src/filesystem/Makefile.am: New. + * src/filesystem/Makefile.in: New. + * src/filesystem/dir.cc: New. + * src/filesystem/ops.cc: New. + * src/filesystem/path.cc: New. + * testsuite/experimental/filesystem/operations/absolute.cc: New. + * testsuite/experimental/filesystem/operations/copy.cc: New. + * testsuite/experimental/filesystem/operations/current_path.cc: New. + * testsuite/experimental/filesystem/path/append/path.cc: New. + * testsuite/experimental/filesystem/path/assign/assign.cc: New. + * testsuite/experimental/filesystem/path/assign/copy.cc: New. + * testsuite/experimental/filesystem/path/compare/compare.cc: New. + * testsuite/experimental/filesystem/path/compare/path.cc: New. + * testsuite/experimental/filesystem/path/compare/strings.cc: New. + * testsuite/experimental/filesystem/path/concat/path.cc: New. + * testsuite/experimental/filesystem/path/concat/strings.cc: New. + * testsuite/experimental/filesystem/path/construct/copy.cc: New. + * testsuite/experimental/filesystem/path/construct/default.cc: New. + * testsuite/experimental/filesystem/path/construct/locale.cc: New. + * testsuite/experimental/filesystem/path/construct/range.cc: New. + * testsuite/experimental/filesystem/path/decompose/extension.cc: New. + * testsuite/experimental/filesystem/path/decompose/filename.cc: New. + * testsuite/experimental/filesystem/path/decompose/parent_path.cc: + New. + * testsuite/experimental/filesystem/path/decompose/relative_path.cc: + New. + * testsuite/experimental/filesystem/path/decompose/root_directory.cc: + New. + * testsuite/experimental/filesystem/path/decompose/root_name.cc: + New. + * testsuite/experimental/filesystem/path/decompose/root_path.cc: + New. + * testsuite/experimental/filesystem/path/decompose/stem.cc: New. + * testsuite/experimental/filesystem/path/generic/generic_string.cc: + New. + * testsuite/experimental/filesystem/path/itr/traversal.cc: New. + * testsuite/experimental/filesystem/path/modifiers/clear.cc: New. + * testsuite/experimental/filesystem/path/modifiers/make_preferred.cc: + New. + * testsuite/experimental/filesystem/path/modifiers/remove_filename.cc: + New. + * testsuite/experimental/filesystem/path/modifiers/replace_extension.cc: + New. + * testsuite/experimental/filesystem/path/modifiers/replace_filename.cc: + New. + * testsuite/experimental/filesystem/path/modifiers/swap.cc: New. + * testsuite/experimental/filesystem/path/nonmember/hash_value.cc: New. + * testsuite/experimental/filesystem/path/query/empty.cc: New. + * testsuite/experimental/filesystem/path/query/has_extension.cc: New. + * testsuite/experimental/filesystem/path/query/has_filename.cc: New. + * testsuite/experimental/filesystem/path/query/has_parent_path.cc: + New. + * testsuite/experimental/filesystem/path/query/has_relative_path.cc: + New. + * testsuite/experimental/filesystem/path/query/has_root_directory.cc: + New. + * testsuite/experimental/filesystem/path/query/has_root_name.cc: + New. + * testsuite/experimental/filesystem/path/query/has_root_path.cc: + New. + * testsuite/experimental/filesystem/path/query/has_stem.cc: New. + * testsuite/experimental/filesystem/path/query/is_relative.cc: New. + * testsuite/util/testsuite_fs.h: New. + 2015-04-30 Edward Smith-Rowland <3dw4rd@verizon.net> Add fundamentals TR container erasure. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index ffa2122f8a7..537ca6f926c 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -49,7 +49,7 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [ # Keep these sync'd with the list in Makefile.am. The first provides an # expandable list at autoconf time; the second provides an expandable list # (i.e., shell variable) at configure time. - m4_define([glibcxx_SUBDIRS],[include libsupc++ src src/c++98 src/c++11 doc po testsuite python]) + m4_define([glibcxx_SUBDIRS],[include libsupc++ src src/c++98 src/c++11 src/filesystem doc po testsuite python]) SUBDIRS='glibcxx_SUBDIRS' # These need to be absolute paths, yet at the same time need to @@ -3903,6 +3903,99 @@ AC_DEFUN([GLIBCXX_DEFAULT_ABI], [ GLIBCXX_CONDITIONAL(ENABLE_CXX11_ABI, test $glibcxx_cxx11_abi = 1) ]) +dnl +dnl Check to see whether to build libstdc++fs.a +dnl +dnl --enable-libstdcxx-filesystem-ts +dnl +AC_DEFUN([GLIBCXX_ENABLE_FILESYSTEM_TS], [ + GLIBCXX_ENABLE(libstdcxx-filesystem-ts,auto,, + [turns on ISO/IEC TS 18822 support], + [permit yes|no|auto]) + + AC_MSG_CHECKING([whether to build Filesystem TS support]) + if test x"$enable_libstdcxx_filesystem_ts" = x"auto"; then + case "${target_os}" in + freebsd*|netbsd*|openbsd*|dragonfly*|darwin*) + enable_libstdcxx_filesystem_ts=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + enable_libstdcxx_filesystem_ts=yes + ;; + solaris*) + enable_libstdcxx_filesystem_ts=yes + ;; + *) + enable_libstdcxx_filesystem_ts=no + ;; + esac + fi + AC_MSG_RESULT($enable_libstdcxx_filesystem_ts) + GLIBCXX_CONDITIONAL(ENABLE_FILESYSTEM_TS, test $enable_libstdcxx_filesystem_ts = yes) +]) + +dnl +dnl Check whether the library calls required by the Filesystem TS are present +dnl and define _GLIBCXX_USE_REALPATH and _GLIBCXX_USE_UTIMENSAT. +dnl +AC_DEFUN([GLIBCXX_CHECK_FILESYSTEM_DEPS], [dnl +dnl + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-exceptions" +dnl + AC_MSG_CHECKING([for realpath]) + AC_CACHE_VAL(glibcxx_cv_realpath, [dnl + GCC_TRY_COMPILE_OR_LINK( + [#include ], + [char *tmp = realpath((const char*)NULL, (char*)NULL);], + [glibcxx_cv_realpath=yes], + [glibcxx_cv_realpath=no]) + ]) + if test $glibcxx_cv_realpath = yes; then + AC_DEFINE(_GLIBCXX_USE_REALPATH, 1, [Define if realpath is available in .]) + fi + AC_MSG_RESULT($glibcxx_cv_realpath) +dnl + AC_MSG_CHECKING([for utimensat]) + AC_CACHE_VAL(glibcxx_cv_utimensat, [dnl + GCC_TRY_COMPILE_OR_LINK( + [ + #include + #include + ], + [ + struct timespec ts[2] = { { 0, UTIME_OMIT }, { 1, 1 } }; + int i = utimensat(AT_FDCWD, "path", ts, 0); + ], + [glibcxx_cv_utimensat=yes], + [glibcxx_cv_utimensat=no]) + ]) + if test $glibcxx_cv_utimensat = yes; then + AC_DEFINE(_GLIBCXX_USE_UTIMENSAT, 1, [Define if utimensat and UTIME_OMIT are available in and AT_FDCWD in .]) + fi + AC_MSG_RESULT($glibcxx_cv_utimensat) +dnl + AC_MSG_CHECKING([for struct stat.st_mtim.tv_nsec]) + AC_CACHE_VAL(glibcxx_cv_st_mtim, [dnl + GCC_TRY_COMPILE_OR_LINK( + [ #include ], + [ + struct stat st; + return st.st_mtim.tv_nsec; + ], + [glibcxx_cv_st_mtim=yes], + [glibcxx_cv_st_mtim=no]) + ]) + if test $glibcxx_cv_st_mtim = yes; then + AC_DEFINE(_GLIBCXX_USE_ST_MTIM, 1, [Define if struct stat has timespec members.]) + fi + AC_MSG_RESULT($glibcxx_cv_st_mtim) +dnl + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) # Macros from the top-level gcc directory. m4_include([../config/gc++filt.m4]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 26ccd22de2d..d763d1bc326 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -54,6 +54,10 @@ /* Define to 1 if you have the `cosl' function. */ #undef HAVE_COSL +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H @@ -132,6 +136,9 @@ /* Define to 1 if you have the `fabsl' function. */ #undef HAVE_FABSL +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + /* Define to 1 if you have the header file. */ #undef HAVE_FENV_H @@ -294,6 +301,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NAN_H +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + /* Define if poll is available in . */ #undef HAVE_POLL @@ -372,6 +382,9 @@ /* Define to 1 if you have the `strtold' function. */ #undef HAVE_STRTOLD +/* Define to 1 if `struct dirent' is a member of `d_type'. */ +#undef HAVE_STRUCT_DIRENT_D_TYPE + /* Define if strxfrm_l is available in . */ #undef HAVE_STRXFRM_L @@ -379,6 +392,10 @@ to different versions. */ #undef HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILIO_H @@ -394,6 +411,10 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MACHINE_H +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H @@ -406,6 +427,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SEM_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATVFS_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H @@ -858,6 +882,9 @@ of TR1 (Chapter 5.1). */ #undef _GLIBCXX_USE_RANDOM_TR1 +/* Define if realpath is available in . */ +#undef _GLIBCXX_USE_REALPATH + /* Defined if sched_yield is available. */ #undef _GLIBCXX_USE_SCHED_YIELD @@ -867,12 +894,19 @@ /* Define if _SC_NPROC_ONLN is available in . */ #undef _GLIBCXX_USE_SC_NPROC_ONLN +/* Define if struct stat has timespec members. */ +#undef _GLIBCXX_USE_ST_MTIM + /* Define if sysctl(), CTL_HW and HW_NCPU are available in . */ #undef _GLIBCXX_USE_SYSCTL_HW_NCPU /* Define if obsolescent tmpnam is available in . */ #undef _GLIBCXX_USE_TMPNAM +/* Define if utimensat and UTIME_OMIT are available in and + AT_FDCWD in . */ +#undef _GLIBCXX_USE_UTIMENSAT + /* Define if code specialized for wchar_t should be used. */ #undef _GLIBCXX_USE_WCHAR_T diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index e94fb9d861f..0a059c6715f 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -638,6 +638,8 @@ DOT DOXYGEN BUILD_INFO_FALSE BUILD_INFO_TRUE +ENABLE_FILESYSTEM_TS_FALSE +ENABLE_FILESYSTEM_TS_TRUE baseline_subdir_switch baseline_dir HWCAP_FLAGS @@ -890,6 +892,7 @@ enable_libstdcxx_visibility enable_libstdcxx_dual_abi with_default_libstdcxx_abi enable_libstdcxx_threads +enable_libstdcxx_filesystem_ts with_gxx_include_dir enable_version_specific_runtime_libs ' @@ -1588,6 +1591,8 @@ Optional Features: support two versions of std::string [default=yes] --enable-libstdcxx-threads enable C++11 threads support [default=auto] + --enable-libstdcxx-filesystem-ts + turns on ISO/IEC TS 18822 support [default=auto] --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory @@ -2552,6 +2557,63 @@ $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_cxx_check_type + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if { as_var=$4; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. @@ -4951,7 +5013,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; } # expandable list at autoconf time; the second provides an expandable list # (i.e., shell variable) at configure time. - SUBDIRS='include libsupc++ src src/c++98 src/c++11 doc po testsuite python' + SUBDIRS='include libsupc++ src src/c++98 src/c++11 src/filesystem doc po testsuite python' # These need to be absolute paths, yet at the same time need to # canonicalize only relative paths, because then amd will not unmount @@ -11593,7 +11655,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11596 "configure" +#line 11658 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11699,7 +11761,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11702 "configure" +#line 11764 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15119,7 +15181,7 @@ fi # # Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style. cat > conftest.$ac_ext << EOF -#line 15122 "configure" +#line 15184 "configure" struct S { ~S(); }; void bar(); void foo() @@ -15471,7 +15533,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF -#line 15474 "configure" +#line 15536 "configure" int main() { typedef bool atomic_type; @@ -15506,7 +15568,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15509 "configure" +#line 15571 "configure" int main() { typedef short atomic_type; @@ -15541,7 +15603,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15544 "configure" +#line 15606 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -15577,7 +15639,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15580 "configure" +#line 15642 "configure" int main() { typedef long long atomic_type; @@ -15656,7 +15718,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 15659 "configure" +#line 15721 "configure" int main() { _Decimal32 d1; @@ -15698,7 +15760,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 15701 "configure" +#line 15763 "configure" template struct same { typedef T2 type; }; @@ -15732,7 +15794,7 @@ $as_echo "$enable_int128" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15735 "configure" +#line 15797 "configure" template struct same { typedef T2 type; }; @@ -78865,6 +78927,457 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +# For Filesystem TS. +for ac_header in fcntl.h dirent.h sys/statvfs.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if test "${ac_cv_search_opendir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then : + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if test "${ac_cv_search_opendir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then : + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + + + + ac_fn_c_check_member "$LINENO" "struct dirent" "d_type" "ac_cv_member_struct_dirent_d_type" " +#include +#ifdef HAVE_DIRENT_H +# include +#else +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + +" +if test "x$ac_cv_member_struct_dirent_d_type" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_DIRENT_D_TYPE 1 +_ACEOF + + +fi + + + + # Check whether --enable-libstdcxx-filesystem-ts was given. +if test "${enable_libstdcxx_filesystem_ts+set}" = set; then : + enableval=$enable_libstdcxx_filesystem_ts; + case "$enableval" in + yes|no|auto) ;; + *) as_fn_error "Unknown argument to enable/disable libstdcxx-filesystem-ts" "$LINENO" 5 ;; + esac + +else + enable_libstdcxx_filesystem_ts=auto +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build Filesystem TS support" >&5 +$as_echo_n "checking whether to build Filesystem TS support... " >&6; } + if test x"$enable_libstdcxx_filesystem_ts" = x"auto"; then + case "${target_os}" in + freebsd*|netbsd*|openbsd*|dragonfly*|darwin*) + enable_libstdcxx_filesystem_ts=yes + ;; + gnu* | linux* | kfreebsd*-gnu | knetbsd*-gnu) + enable_libstdcxx_filesystem_ts=yes + ;; + solaris*) + enable_libstdcxx_filesystem_ts=yes + ;; + *) + enable_libstdcxx_filesystem_ts=no + ;; + esac + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_libstdcxx_filesystem_ts" >&5 +$as_echo "$enable_libstdcxx_filesystem_ts" >&6; } + + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-exceptions" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for realpath" >&5 +$as_echo_n "checking for realpath... " >&6; } + if test "${glibcxx_cv_realpath+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test x$gcc_no_link = xyes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char *tmp = realpath((const char*)NULL, (char*)NULL); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_realpath=yes +else + glibcxx_cv_realpath=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char *tmp = realpath((const char*)NULL, (char*)NULL); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + glibcxx_cv_realpath=yes +else + glibcxx_cv_realpath=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi + + if test $glibcxx_cv_realpath = yes; then + +$as_echo "#define _GLIBCXX_USE_REALPATH 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_realpath" >&5 +$as_echo "$glibcxx_cv_realpath" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utimensat" >&5 +$as_echo_n "checking for utimensat... " >&6; } + if test "${glibcxx_cv_utimensat+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test x$gcc_no_link = xyes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + struct timespec ts[2] = { { 0, UTIME_OMIT }, { 1, 1 } }; + int i = utimensat(AT_FDCWD, "path", ts, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_utimensat=yes +else + glibcxx_cv_utimensat=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + struct timespec ts[2] = { { 0, UTIME_OMIT }, { 1, 1 } }; + int i = utimensat(AT_FDCWD, "path", ts, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + glibcxx_cv_utimensat=yes +else + glibcxx_cv_utimensat=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi + + if test $glibcxx_cv_utimensat = yes; then + +$as_echo "#define _GLIBCXX_USE_UTIMENSAT 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_utimensat" >&5 +$as_echo "$glibcxx_cv_utimensat" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat.st_mtim.tv_nsec" >&5 +$as_echo_n "checking for struct stat.st_mtim.tv_nsec... " >&6; } + if test "${glibcxx_cv_st_mtim+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test x$gcc_no_link = xyes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + #include +int +main () +{ + + struct stat st; + return st.st_mtim.tv_nsec; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_st_mtim=yes +else + glibcxx_cv_st_mtim=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + if test x$gcc_no_link = xyes; then + as_fn_error "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + #include +int +main () +{ + + struct stat st; + return st.st_mtim.tv_nsec; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + glibcxx_cv_st_mtim=yes +else + glibcxx_cv_st_mtim=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi + + if test $glibcxx_cv_st_mtim = yes; then + +$as_echo "#define _GLIBCXX_USE_ST_MTIM 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_st_mtim" >&5 +$as_echo "$glibcxx_cv_st_mtim" >&6; } + CXXFLAGS="$ac_save_CXXFLAGS" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + # Define documentation rules conditionally. # See if makeinfo has been installed and is modern enough @@ -79488,6 +80001,15 @@ else fi + if test $enable_libstdcxx_filesystem_ts = yes; then + ENABLE_FILESYSTEM_TS_TRUE= + ENABLE_FILESYSTEM_TS_FALSE='#' +else + ENABLE_FILESYSTEM_TS_TRUE='#' + ENABLE_FILESYSTEM_TS_FALSE= +fi + + cat >confcache <<\_ACEOF @@ -79713,7 +80235,7 @@ ac_config_files="$ac_config_files doc/xsl/customization.xsl" # append it here. Only modify Makefiles that have just been created. # # Also, get rid of this simulated-VPATH thing that automake does. -ac_config_files="$ac_config_files include/Makefile libsupc++/Makefile src/Makefile src/c++98/Makefile src/c++11/Makefile doc/Makefile po/Makefile testsuite/Makefile python/Makefile" +ac_config_files="$ac_config_files include/Makefile libsupc++/Makefile src/Makefile src/c++98/Makefile src/c++11/Makefile src/filesystem/Makefile doc/Makefile po/Makefile testsuite/Makefile python/Makefile" ac_config_commands="$ac_config_commands generate-headers" @@ -79912,6 +80434,10 @@ if test -z "${GLIBCXX_LDBL_COMPAT_TRUE}" && test -z "${GLIBCXX_LDBL_COMPAT_FALSE as_fn_error "conditional \"GLIBCXX_LDBL_COMPAT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_FILESYSTEM_TS_TRUE}" && test -z "${ENABLE_FILESYSTEM_TS_FALSE}"; then + as_fn_error "conditional \"ENABLE_FILESYSTEM_TS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${BUILD_INFO_TRUE}" && test -z "${BUILD_INFO_FALSE}"; then as_fn_error "conditional \"BUILD_INFO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -80933,6 +81459,7 @@ do "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/c++98/Makefile") CONFIG_FILES="$CONFIG_FILES src/c++98/Makefile" ;; "src/c++11/Makefile") CONFIG_FILES="$CONFIG_FILES src/c++11/Makefile" ;; + "src/filesystem/Makefile") CONFIG_FILES="$CONFIG_FILES src/filesystem/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; @@ -82760,6 +83287,17 @@ _EOF ;; "src/c++11/Makefile":F) cat > vpsed$$ << \_EOF s!`test -f '$<' || echo '$(srcdir)/'`!! +_EOF + sed -f vpsed$$ $ac_file > tmp$$ + mv tmp$$ $ac_file + rm vpsed$$ + echo 'MULTISUBDIR =' >> $ac_file + ml_norecursion=yes + . ${multi_basedir}/config-ml.in + { ml_norecursion=; unset ml_norecursion;} + ;; + "src/filesystem/Makefile":F) cat > vpsed$$ << \_EOF +s!`test -f '$<' || echo '$(srcdir)/'`!! _EOF sed -f vpsed$$ $ac_file > tmp$$ mv tmp$$ $ac_file diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 7a7c1d820fa..4b39bfa0262 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -402,6 +402,12 @@ GLIBCXX_CONFIGURE_TESTSUITE # For gthread support. Depends on GLIBCXX_ENABLE_SYMVERS. GLIBCXX_CHECK_GTHREADS +# For Filesystem TS. +AC_CHECK_HEADERS([fcntl.h dirent.h sys/statvfs.h]) +AC_STRUCT_DIRENT_D_TYPE +GLIBCXX_ENABLE_FILESYSTEM_TS +GLIBCXX_CHECK_FILESYSTEM_DEPS + # Define documentation rules conditionally. # See if makeinfo has been installed and is modern enough diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index d582dff8708..32be43e7e04 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -128,6 +128,7 @@ bits_headers = \ ${bits_srcdir}/postypes.h \ ${bits_srcdir}/predefined_ops.h \ ${bits_srcdir}/ptr_traits.h \ + ${bits_srcdir}/quoted_string.h \ ${bits_srcdir}/random.h \ ${bits_srcdir}/random.tcc \ ${bits_srcdir}/range_access.h \ @@ -663,7 +664,19 @@ experimental_headers = \ ${experimental_srcdir}/type_traits \ ${experimental_srcdir}/unordered_map \ ${experimental_srcdir}/unordered_set \ - ${experimental_srcdir}/vector + ${experimental_srcdir}/vector \ + ${experimental_filesystem_headers} + +if ENABLE_FILESYSTEM_TS +experimental_filesystem_headers = \ + ${experimental_srcdir}/filesystem \ + ${experimental_srcdir}/fs_dir.h \ + ${experimental_srcdir}/fs_fwd.h \ + ${experimental_srcdir}/fs_ops.h \ + ${experimental_srcdir}/fs_path.h +else +experimental_filesystem_headers = +endif # This is the common subset of C++ files that all three "C" header models use. c_base_srcdir = $(C_INCLUDE_DIR) diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index f9328e167eb..e59ee689a26 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -396,6 +396,7 @@ bits_headers = \ ${bits_srcdir}/postypes.h \ ${bits_srcdir}/predefined_ops.h \ ${bits_srcdir}/ptr_traits.h \ + ${bits_srcdir}/quoted_string.h \ ${bits_srcdir}/random.h \ ${bits_srcdir}/random.tcc \ ${bits_srcdir}/range_access.h \ @@ -930,7 +931,16 @@ experimental_headers = \ ${experimental_srcdir}/type_traits \ ${experimental_srcdir}/unordered_map \ ${experimental_srcdir}/unordered_set \ - ${experimental_srcdir}/vector + ${experimental_srcdir}/vector \ + ${experimental_filesystem_headers} + +@ENABLE_FILESYSTEM_TS_FALSE@experimental_filesystem_headers = +@ENABLE_FILESYSTEM_TS_TRUE@experimental_filesystem_headers = \ +@ENABLE_FILESYSTEM_TS_TRUE@ ${experimental_srcdir}/filesystem \ +@ENABLE_FILESYSTEM_TS_TRUE@ ${experimental_srcdir}/fs_dir.h \ +@ENABLE_FILESYSTEM_TS_TRUE@ ${experimental_srcdir}/fs_fwd.h \ +@ENABLE_FILESYSTEM_TS_TRUE@ ${experimental_srcdir}/fs_ops.h \ +@ENABLE_FILESYSTEM_TS_TRUE@ ${experimental_srcdir}/fs_path.h # This is the common subset of C++ files that all three "C" header models use. diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h index 9b49617b7a9..8878aa1310b 100644 --- a/libstdc++-v3/include/bits/locale_conv.h +++ b/libstdc++-v3/include/bits/locale_conv.h @@ -51,6 +51,105 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ + template + bool + __do_str_codecvt(const _InChar* __first, const _InChar* __last, + _OutStr& __outstr, const _Codecvt& __cvt, _State& __state, + size_t& __count, _Fn __fn) + { + size_t __outchars = 0; + auto __next = __first; + const auto __maxlen = __cvt.max_length(); + + codecvt_base::result __result; + do + { + __outstr.resize(__outstr.size() + (__last - __next) + __maxlen); + auto __outnext = &__outstr.front() + __outchars; + auto const __outlast = &__outstr.back() + 1; + __result = (__cvt.*__fn)(__state, __next, __last, __next, + __outnext, __outlast, __outnext); + __outchars = __outnext - &__outstr.front(); + } + while (__result == codecvt_base::partial && __next != __last + && (__outstr.size() - __outchars) < __maxlen); + + if (__result == codecvt_base::error) + return false; + + if (__result == codecvt_base::noconv) + { + __outstr.assign(__first, __last); + __count = __last - __first; + } + else + { + __outstr.resize(__outchars); + __count = __next - __first; + } + + return true; + } + + // Convert narrow character string to wide. + template + inline bool + __str_codecvt_in(const char* __first, const char* __last, + basic_string<_CharT, _Traits, _Alloc>& __outstr, + const codecvt<_CharT, char, _State>& __cvt, + _State& __state, size_t& __count) + { + using _Codecvt = codecvt<_CharT, char, _State>; + using _ConvFn + = codecvt_base::result + (_Codecvt::*)(_State&, const char*, const char*, const char*&, + _CharT*, _CharT*, _CharT*&) const; + _ConvFn __fn = &codecvt<_CharT, char, _State>::in; + return __do_str_codecvt(__first, __last, __outstr, __cvt, __state, + __count, __fn); + } + + template + inline bool + __str_codecvt_in(const char* __first, const char* __last, + basic_string<_CharT, _Traits, _Alloc>& __outstr, + const codecvt<_CharT, char, _State>& __cvt) + { + _State __state = {}; + size_t __n; + return __str_codecvt_in(__first, __last, __outstr, __cvt, __state, __n); + } + + // Convert wide character string to narrow. + template + inline bool + __str_codecvt_out(const _CharT* __first, const _CharT* __last, + basic_string& __outstr, + const codecvt<_CharT, char, _State>& __cvt, + _State& __state, size_t& __count) + { + using _Codecvt = codecvt<_CharT, char, _State>; + using _ConvFn + = codecvt_base::result + (_Codecvt::*)(_State&, const _CharT*, const _CharT*, const _CharT*&, + char*, char*, char*&) const; + _ConvFn __fn = &codecvt<_CharT, char, _State>::out; + return __do_str_codecvt(__first, __last, __outstr, __cvt, __state, + __count, __fn); + } + + template + inline bool + __str_codecvt_out(const _CharT* __first, const _CharT* __last, + basic_string& __outstr, + const codecvt<_CharT, char, _State>& __cvt) + { + _State __state = {}; + size_t __n; + return __str_codecvt_out(__first, __last, __outstr, __cvt, __state, __n); + } + /// String conversions template, @@ -136,9 +235,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION wide_string from_bytes(const char* __first, const char* __last) { - auto __errstr = _M_with_strings ? &_M_wide_err_string : nullptr; - _ConvFn __fn = &_Codecvt::in; - return _M_conv(__first, __last, __errstr, __fn); + if (!_M_with_cvtstate) + _M_state = state_type(); + wide_string __out{ _M_wide_err_string.get_allocator() }; + if (__str_codecvt_in(__first, __last, __out, *_M_cvt, _M_state, + _M_count)) + return __out; + if (_M_with_strings) + return _M_wide_err_string; + __throw_range_error("wstring_convert::from_bytes"); } /// @} @@ -166,9 +271,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION byte_string to_bytes(const _Elem* __first, const _Elem* __last) { - auto __errstr = _M_with_strings ? &_M_byte_err_string : nullptr; - _ConvFn<_Elem, char> __fn = &_Codecvt::out; - return _M_conv(__first, __last, __errstr, __fn); + if (!_M_with_cvtstate) + _M_state = state_type(); + byte_string __out{ _M_byte_err_string.get_allocator() }; + if (__str_codecvt_out(__first, __last, __out, *_M_cvt, _M_state, + _M_count)) + return __out; + if (_M_with_strings) + return _M_byte_err_string; + __throw_range_error("wstring_convert::to_bytes"); } /// @} @@ -181,56 +292,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION state_type state() const { return _M_state; } private: - template - using _ConvFn - = codecvt_base::result - (_Codecvt::*)(state_type&, const _InC*, const _InC*, const _InC*&, - _OutC*, _OutC*, _OutC*&) const; - - template - _OutStr - _M_conv(const _InChar* __first, const _InChar* __last, - const _OutStr* __err, _MemFn __memfn) - { - if (!_M_with_cvtstate) - _M_state = state_type(); - - auto __outstr = __err ? _OutStr(__err->get_allocator()) : _OutStr(); - size_t __outchars = 0; - auto __next = __first; - const auto __maxlen = _M_cvt->max_length(); - - codecvt_base::result __result; - do - { - __outstr.resize(__outstr.size() + (__last - __next) + __maxlen); - auto __outnext = &__outstr.front() + __outchars; - auto const __outlast = &__outstr.back() + 1; - __result = ((*_M_cvt).*__memfn)(_M_state, __next, __last, __next, - __outnext, __outlast, __outnext); - __outchars = __outnext - &__outstr.front(); - } - while (__result == codecvt_base::partial && __next != __last - && (__outstr.size() - __outchars) < __maxlen); - - if (__result == codecvt_base::noconv) - { - __outstr.assign(__first, __last); - _M_count = __outstr.size(); - return __outstr; - } - - __outstr.resize(__outchars); - _M_count = __next - __first; - - if (__result != codecvt_base::error) - return __outstr; - else if (__err) - return *__err; - else - __throw_range_error("wstring_convert"); - } - unique_ptr<_Codecvt> _M_cvt; byte_string _M_byte_err_string; wide_string _M_wide_err_string; diff --git a/libstdc++-v3/include/bits/quoted_string.h b/libstdc++-v3/include/bits/quoted_string.h new file mode 100644 index 00000000000..0805e08cc43 --- /dev/null +++ b/libstdc++-v3/include/bits/quoted_string.h @@ -0,0 +1,164 @@ +// Helpers for quoted stream manipulators -*- C++ -*- + +// Copyright (C) 2013-2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/quoted_string.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iomanip} + */ + +#ifndef _GLIBCXX_QUOTED_STRING_H +#define _GLIBCXX_QUOTED_STRING_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ + namespace __detail { + _GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Struct for delimited strings. + */ + template + struct _Quoted_string + { + static_assert(is_reference<_String>::value + || is_pointer<_String>::value, + "String type must be pointer or reference"); + + _Quoted_string(_String __str, _CharT __del, _CharT __esc) + : _M_string(__str), _M_delim{__del}, _M_escape{__esc} + { } + + _Quoted_string& + operator=(_Quoted_string&) = delete; + + _String _M_string; + _CharT _M_delim; + _CharT _M_escape; + }; + + /** + * @brief Inserter for quoted strings. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 2344 quoted()'s interaction with padding is unclear + */ + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const _Quoted_string& __str) + { + std::basic_ostringstream<_CharT, _Traits> __ostr; + __ostr << __str._M_delim; + for (const _CharT* __c = __str._M_string; *__c; ++__c) + { + if (*__c == __str._M_delim || *__c == __str._M_escape) + __ostr << __str._M_escape; + __ostr << *__c; + } + __ostr << __str._M_delim; + + return __os << __ostr.str(); + } + + /** + * @brief Inserter for quoted strings. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 2344 quoted()'s interaction with padding is unclear + */ + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const _Quoted_string<_String, _CharT>& __str) + { + std::basic_ostringstream<_CharT, _Traits> __ostr; + __ostr << __str._M_delim; + for (auto& __c : __str._M_string) + { + if (__c == __str._M_delim || __c == __str._M_escape) + __ostr << __str._M_escape; + __ostr << __c; + } + __ostr << __str._M_delim; + + return __os << __ostr.str(); + } + + /** + * @brief Extractor for delimited strings. + * The left and right delimiters can be different. + */ + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + const _Quoted_string&, + _CharT>& __str) + { + _CharT __c; + __is >> __c; + if (!__is.good()) + return __is; + if (__c != __str._M_delim) + { + __is.unget(); + __is >> __str._M_string; + return __is; + } + __str._M_string.clear(); + std::ios_base::fmtflags __flags + = __is.flags(__is.flags() & ~std::ios_base::skipws); + do + { + __is >> __c; + if (!__is.good()) + break; + if (__c == __str._M_escape) + { + __is >> __c; + if (!__is.good()) + break; + } + else if (__c == __str._M_delim) + break; + __str._M_string += __c; + } + while (true); + __is.setf(__flags); + + return __is; + } + + _GLIBCXX_END_NAMESPACE_VERSION + } // namespace __detail +} // namespace std + +#endif // C++11 +#endif /* _GLIBCXX_QUOTED_STRING_H */ diff --git a/libstdc++-v3/include/experimental/filesystem b/libstdc++-v3/include/experimental/filesystem new file mode 100644 index 00000000000..db7ab1117da --- /dev/null +++ b/libstdc++-v3/include/experimental/filesystem @@ -0,0 +1,77 @@ +// -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file experimental/filesystem + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_FILESYSTEM +#define _GLIBCXX_EXPERIMENTAL_FILESYSTEM 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include + +#define __cpp_lib_experimental_filesystem 201406 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +namespace filesystem +{ +inline namespace v1 +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @ingroup filesystem + */ + inline std::string filesystem_error::_M_gen_what() + { + std::string __what = "filesystem error: "; + __what += system_error::what(); + if (!_M_path1.empty()) + __what += " [" + _M_path1.string() + ']'; + if (!_M_path2.empty()) + __what += " [" + _M_path2.string() + ']'; + return __what; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace v1 +} // namespace filesystem +} // namespace experimental +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_EXPERIMENTAL_FILESYSTEM diff --git a/libstdc++-v3/include/experimental/fs_dir.h b/libstdc++-v3/include/experimental/fs_dir.h new file mode 100644 index 00000000000..0538fd2a697 --- /dev/null +++ b/libstdc++-v3/include/experimental/fs_dir.h @@ -0,0 +1,326 @@ +// Filesystem directory utilities -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file experimental/fs_dir.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{experimental/filesystem} + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_FS_DIR_H +#define _GLIBCXX_EXPERIMENTAL_FS_DIR_H 1 + +#if __cplusplus < 201103L +# include +#else +# include +# include +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +namespace filesystem +{ +inline namespace v1 +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @ingroup filesystem + * @{ + */ + + class file_status + { + public: + // constructors + explicit + file_status(file_type __ft = file_type::none, + perms __prms = perms::unknown) noexcept + : _M_type(__ft), _M_perms(__prms) { } + + file_status(const file_status&) noexcept = default; + file_status(file_status&&) noexcept = default; + ~file_status() = default; + + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&) noexcept = default; + + // observers + file_type type() const noexcept { return _M_type; } + perms permissions() const noexcept { return _M_perms; } + + // modifiers + void type(file_type __ft) noexcept { _M_type = __ft; } + void permissions(perms __prms) noexcept { _M_perms = __prms; } + + private: + file_type _M_type; + perms _M_perms; + }; + +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + class directory_entry + { + public: + // constructors and destructor + directory_entry() noexcept = default; + directory_entry(const directory_entry&) = default; + directory_entry(directory_entry&&) noexcept = default; + explicit directory_entry(const filesystem::path& __p) : _M_path(__p) { } + ~directory_entry() = default; + + // modifiers + directory_entry& operator=(const directory_entry&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + void assign(const filesystem::path& __p) { _M_path = __p; } + + void + replace_filename(const filesystem::path& __p) + { _M_path = _M_path.parent_path() / __p; } + + // observers + const filesystem::path& path() const noexcept { return _M_path; } + operator const filesystem::path&() const noexcept { return _M_path; } + + file_status + status() const + { return filesystem::status(_M_path); } + + file_status + status(error_code& __ec) const noexcept + { return filesystem::status(_M_path, __ec); } + + file_status + symlink_status() const + { return filesystem::symlink_status(_M_path); } + + file_status + symlink_status(error_code& __ec) const noexcept + { return filesystem::symlink_status(_M_path, __ec); } + + bool + operator< (const directory_entry& __rhs) const noexcept + { return _M_path < __rhs._M_path; } + + bool + operator==(const directory_entry& __rhs) const noexcept + { return _M_path == __rhs._M_path; } + + bool + operator!=(const directory_entry& __rhs) const noexcept + { return _M_path != __rhs._M_path; } + + bool + operator<=(const directory_entry& __rhs) const noexcept + { return _M_path <= __rhs._M_path; } + + bool + operator> (const directory_entry& __rhs) const noexcept + { return _M_path > __rhs._M_path; } + + bool + operator>=(const directory_entry& __rhs) const noexcept + { return _M_path >= __rhs._M_path; } + + private: + filesystem::path _M_path; + }; + + struct _Dir; + class recursive_directory_iterator; + + class directory_iterator + { + public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef const directory_entry* pointer; + typedef const directory_entry& reference; + typedef input_iterator_tag iterator_category; + + directory_iterator() noexcept = default; + + explicit + directory_iterator(const path& __p) + : directory_iterator(__p, directory_options::none, nullptr) { } + + directory_iterator(const path& __p, directory_options __options) + : directory_iterator(__p, __options, nullptr) { } + + directory_iterator(const path& __p, error_code& __ec) noexcept + : directory_iterator(__p, directory_options::none, __ec) { } + + directory_iterator(const path& __p, + directory_options __options, error_code& __ec) noexcept + : directory_iterator(__p, __options, &__ec) { } + + directory_iterator(const directory_iterator& rhs) = default; + + directory_iterator(directory_iterator&& rhs) noexcept = default; + + ~directory_iterator() = default; + + directory_iterator& operator=(const directory_iterator& rhs) = default; + directory_iterator& operator=(directory_iterator&& rhs) noexcept = default; + + const directory_entry& operator*() const; + const directory_entry* operator->() const { return &**this; } + directory_iterator& operator++(); + directory_iterator& increment(error_code& __ec) noexcept; + + directory_iterator operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + friend bool + operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs) + { return __lhs._M_dir == __rhs._M_dir; } + + private: + directory_iterator(const path&, directory_options, error_code*); + directory_iterator(std::shared_ptr<_Dir>, error_code*); + + friend class recursive_directory_iterator; + + std::shared_ptr<_Dir> _M_dir; + }; + + inline directory_iterator + begin(directory_iterator __iter) { return __iter; } + + inline directory_iterator + end(directory_iterator) { return directory_iterator(); } + + inline bool + operator!=(const directory_iterator& __lhs, const directory_iterator& __rhs) + { return !(__lhs == __rhs); } + + class recursive_directory_iterator + { + public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef const directory_entry* pointer; + typedef const directory_entry& reference; + typedef input_iterator_tag iterator_category; + + recursive_directory_iterator() noexcept = default; + + explicit + recursive_directory_iterator(const path& __p) + : recursive_directory_iterator(__p, directory_options::none, nullptr) { } + + recursive_directory_iterator(const path& __p, directory_options __options) + : recursive_directory_iterator(__p, __options, nullptr) { } + + recursive_directory_iterator(const path& __p, + directory_options __options, + error_code& __ec) noexcept + : recursive_directory_iterator(__p, __options, &__ec) { } + + recursive_directory_iterator(const path& __p, error_code& __ec) noexcept + : recursive_directory_iterator(__p, directory_options::none, &__ec) { } + + recursive_directory_iterator( + const recursive_directory_iterator&) = default; + + recursive_directory_iterator( + recursive_directory_iterator&&) noexcept = default; + + ~recursive_directory_iterator(); + + // observers + directory_options options() const { return _M_options; } + int depth() const; + bool recursion_pending() const { return _M_pending; } + + const directory_entry& operator*() const; + const directory_entry* operator->() const { return &**this; } + + // modifiers + recursive_directory_iterator& + operator=(const recursive_directory_iterator& rhs) noexcept; + recursive_directory_iterator& + operator=(recursive_directory_iterator&& rhs) noexcept; + + recursive_directory_iterator& operator++(); + recursive_directory_iterator& increment(error_code& __ec) noexcept; + + recursive_directory_iterator operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + void pop(); + + void disable_recursion_pending() { _M_pending = false; } + + friend bool + operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) + { return __lhs._M_dirs == __rhs._M_dirs; } + + private: + recursive_directory_iterator(const path&, directory_options, error_code*); + + struct _Dir_stack; + std::shared_ptr<_Dir_stack> _M_dirs; + directory_options _M_options; + bool _M_pending; + }; + + inline recursive_directory_iterator + begin(recursive_directory_iterator __iter) { return __iter; } + + inline recursive_directory_iterator + end(recursive_directory_iterator) { return recursive_directory_iterator(); } + + inline bool + operator!=(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) + { return !(__lhs == __rhs); } + +_GLIBCXX_END_NAMESPACE_CXX11 + + // @} group filesystem +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace v1 +} // namespace filesystem +} // namespace experimental +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_EXPERIMENTAL_FS_DIR_H diff --git a/libstdc++-v3/include/experimental/fs_fwd.h b/libstdc++-v3/include/experimental/fs_fwd.h new file mode 100644 index 00000000000..a5ed2c5de0e --- /dev/null +++ b/libstdc++-v3/include/experimental/fs_fwd.h @@ -0,0 +1,289 @@ +// Filesystem declarations -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file experimental/filesystem + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_FS_FWD_H +#define _GLIBCXX_EXPERIMENTAL_FS_FWD_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +namespace filesystem +{ +inline namespace v1 +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if _GLIBCXX_USE_CXX11_ABI + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +#endif + + /** + * @defgroup filesystem + * @ingroup experimental + * + * Utilities for performing operations on file systems and their components, + * such as paths, regular files, and directories. + * + * @{ + */ + + class file_status; +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + class path; + class filesystem_error; + class directory_entry; + class directory_iterator; + class recursive_directory_iterator; +_GLIBCXX_END_NAMESPACE_CXX11 + + struct space_info + { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; + }; + + enum class 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 + }; + + /// Bitmask type + enum class 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 + }; + + constexpr copy_options + operator&(copy_options __x, copy_options __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr copy_options + operator|(copy_options __x, copy_options __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr copy_options + operator^(copy_options __x, copy_options __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr copy_options + operator~(copy_options __x) + { + using __utype = typename std::underlying_type::type; + return static_cast(~static_cast<__utype>(__x)); + } + + inline copy_options& + operator&=(copy_options& __x, copy_options __y) + { return __x = __x & __y; } + + inline copy_options& + operator|=(copy_options& __x, copy_options __y) + { return __x = __x | __y; } + + inline copy_options& + operator^=(copy_options& __x, copy_options __y) + { return __x = __x ^ __y; } + + + /// Bitmask type + enum class 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, + add_perms = 0x10000, + remove_perms = 0x20000, + resolve_symlinks = 0x40000 + }; + + constexpr perms + operator&(perms __x, perms __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr perms + operator|(perms __x, perms __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr perms + operator^(perms __x, perms __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr perms + operator~(perms __x) + { + using __utype = typename std::underlying_type::type; + return static_cast(~static_cast<__utype>(__x)); + } + + inline perms& + operator&=(perms& __x, perms __y) + { return __x = __x & __y; } + + inline perms& + operator|=(perms& __x, perms __y) + { return __x = __x | __y; } + + inline perms& + operator^=(perms& __x, perms __y) + { return __x = __x ^ __y; } + + // Bitmask type + enum class directory_options : unsigned char { + none = 0, follow_directory_symlink = 1, skip_permission_denied = 2 + }; + + constexpr directory_options + operator&(directory_options __x, directory_options __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr directory_options + operator|(directory_options __x, directory_options __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr directory_options + operator^(directory_options __x, directory_options __y) + { + using __utype = typename std::underlying_type::type; + return static_cast( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr directory_options + operator~(directory_options __x) + { + using __utype = typename std::underlying_type::type; + return static_cast(~static_cast<__utype>(__x)); + } + + inline directory_options& + operator&=(directory_options& __x, directory_options __y) + { return __x = __x & __y; } + + inline directory_options& + operator|=(directory_options& __x, directory_options __y) + { return __x = __x | __y; } + + inline directory_options& + operator^=(directory_options& __x, directory_options __y) + { return __x = __x ^ __y; } + + typedef chrono::time_point file_time_type; + + // operational functions + + void copy(const path& __from, const path& __to, copy_options __options); + void copy(const path& __from, const path& __to, copy_options __options, + error_code&) noexcept; + + 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&) noexcept; + + path current_path(); + + file_status status(const path&); + file_status status(const path&, error_code&) noexcept; + + bool status_known(file_status) noexcept; + + file_status symlink_status(const path&); + file_status symlink_status(const path&, error_code&) noexcept; + + bool is_regular_file(file_status) noexcept; + bool is_symlink(file_status) noexcept; + + // @} group filesystem +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace v1 +} // namespace filesystem +} // namespace experimental +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_EXPERIMENTAL_FS_FWD_H diff --git a/libstdc++-v3/include/experimental/fs_ops.h b/libstdc++-v3/include/experimental/fs_ops.h new file mode 100644 index 00000000000..0878fbb8f8d --- /dev/null +++ b/libstdc++-v3/include/experimental/fs_ops.h @@ -0,0 +1,291 @@ +// Filesystem operational functions -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your __option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file experimental/filesystem + * This is a TS C++ Library header. + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_FS_OPS_H +#define _GLIBCXX_EXPERIMENTAL_FS_OPS_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +namespace filesystem +{ +inline namespace v1 +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @ingroup filesystem + * @{ + */ + + path absolute(const path& __p, const path& __base = current_path()); + + path canonical(const path& __p, const path& __base = current_path()); + path canonical(const path& p, error_code& ec); + path canonical(const path& p, const path& base, error_code& ec); + + inline void + copy(const path& __from, const path& __to) + { copy(__from, __to, copy_options::none); } + + inline void + copy(const path& __from, const path& __to, error_code& __ec) noexcept + { copy(__from, __to, copy_options::none, __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) noexcept; + + inline bool + copy_file(const path& __from, const path& __to) + { return copy_file(__from, __to, copy_options::none); } + + inline bool + copy_file(const path& __from, const path& __to, error_code& __ec) noexcept + { return copy_file(__from, __to, copy_options::none, __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) noexcept; + + 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) noexcept; + + 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; + + inline bool + exists(file_status __s) noexcept + { return status_known(__s) && __s.type() != file_type::not_found; } + + inline bool + exists(const path& __p) + { return exists(status(__p)); } + + inline bool + exists(const path& __p, error_code& __ec) noexcept + { return exists(status(__p, __ec)); } + + 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; + + inline bool + is_block_file(file_status __s) noexcept + { return __s.type() == file_type::block; } + + inline bool + is_block_file(const path& __p) + { return is_block_file(status(__p)); } + + inline bool + is_block_file(const path& __p, error_code& __ec) noexcept + { return is_block_file(status(__p, __ec)); } + + inline bool + is_character_file(file_status __s) noexcept + { return __s.type() == file_type::character; } + + inline bool + is_character_file(const path& __p) + { return is_character_file(status(__p)); } + + inline bool + is_character_file(const path& __p, error_code& __ec) noexcept + { return is_character_file(status(__p, __ec)); } + + inline bool + is_directory(file_status __s) noexcept + { return __s.type() == file_type::directory; } + + inline bool + is_directory(const path& __p) + { return is_directory(status(__p)); } + + inline bool + is_directory(const path& __p, error_code& __ec) noexcept + { return is_directory(status(__p, __ec)); } + + bool is_empty(const path& __p); + bool is_empty(const path& __p, error_code& __ec) noexcept; + + inline bool + is_fifo(file_status __s) noexcept + { return __s.type() == file_type::fifo; } + + inline bool + is_fifo(const path& __p) + { return is_fifo(status(__p)); } + + inline bool + is_fifo(const path& __p, error_code& __ec) noexcept + { return is_fifo(status(__p, __ec)); } + + inline bool + is_other(file_status __s) noexcept + { + return exists(__s) && !is_regular_file(__s) && !is_directory(__s) + && !is_symlink(__s); + } + + inline bool + is_other(const path& __p) + { return is_other(status(__p)); } + + inline bool + is_other(const path& __p, error_code& __ec) noexcept + { return is_other(status(__p, __ec)); } + + inline bool + is_regular_file(file_status __s) noexcept + { return __s.type() == file_type::regular; } + + inline bool + is_regular_file(const path& __p) + { return is_regular_file(status(__p)); } + + inline bool + is_regular_file(const path& __p, error_code& __ec) noexcept + { return is_regular_file(status(__p, __ec)); } + + inline bool + is_socket(file_status __s) noexcept + { return __s.type() == file_type::socket; } + + inline bool + is_socket(const path& __p) + { return is_socket(status(__p)); } + + inline bool + is_socket(const path& __p, error_code& __ec) noexcept + { return is_socket(status(__p, __ec)); } + + inline bool + is_symlink(file_status __s) noexcept + { return __s.type() == file_type::symlink; } + + inline bool + is_symlink(const path& __p) + { return is_symlink(symlink_status(__p)); } + + inline bool + is_symlink(const path& __p, error_code& __ec) noexcept + { return is_symlink(symlink_status(__p, __ec)); } + + 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); + void permissions(const path& __p, perms prms, error_code& __ec) noexcept; + + path read_symlink(const path& __p); + path read_symlink(const path& __p, 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) noexcept; + + 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; + + inline bool status_known(file_status __s) noexcept + { return __s.type() != file_type::none; } + + file_status symlink_status(const path& __p); + file_status symlink_status(const path& __p, error_code& __ec) noexcept; + + path system_complete(const path& __p); + path system_complete(const path& __p, error_code& __ec); + + path temp_directory_path(); + path temp_directory_path(error_code& __ec); + + // @} group filesystem +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace v1 +} // namespace filesystem +} // namespace experimental +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_EXPERIMENTAL_FS_OPS_H diff --git a/libstdc++-v3/include/experimental/fs_path.h b/libstdc++-v3/include/experimental/fs_path.h new file mode 100644 index 00000000000..ffc49266b7a --- /dev/null +++ b/libstdc++-v3/include/experimental/fs_path.h @@ -0,0 +1,1014 @@ +// Class filesystem::path -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file experimental/fs_path.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{experimental/filesystem} + */ + +#ifndef _GLIBCXX_EXPERIMENTAL_FS_PATH_H +#define _GLIBCXX_EXPERIMENTAL_FS_PATH_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1 +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace experimental +{ +namespace filesystem +{ +inline namespace v1 +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + /** + * @ingroup filesystem + * @{ + */ + + /// A filesystem path. + class path + { + template + struct __is_encoded_char : std::false_type { }; + + template> + using __is_path_iter_src + = __and_<__is_encoded_char, + std::is_base_of>; + + template + static __is_path_iter_src<_Iter> + __is_path_src(_Iter, int); + + template + static __is_encoded_char<_CharT> + __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); + + template + static std::false_type + __is_path_src(const _Unknown&, ...); + + template + struct __constructible_from; + + template + struct __constructible_from<_Iter, _Iter> + : __is_path_iter_src<_Iter> + { }; + + template + struct __constructible_from<_Source, void> + : decltype(__is_path_src(std::declval<_Source>(), 0)) + { }; + + template + using _Path = typename + std::enable_if<__and_<__not_>, + __constructible_from<_Tp1, _Tp2>>::value, + path>::type; + + template + static _Source + _S_range_begin(_Source __begin) { return __begin; } + + struct __null_terminated { }; + + template + static __null_terminated + _S_range_end(_Source) { return {}; } + + template + static const _CharT* + _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data(); } + + template + static const _CharT* + _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data() + __str.size(); } + + template())), + typename _Val = typename std::iterator_traits<_Iter>::value_type> + using __value_type_is_char + = typename std::enable_if::value>::type; + + public: +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + typedef wchar_t value_type; + static constexpr value_type preferred_separator = L'\\'; +#else + typedef char value_type; + static constexpr value_type preferred_separator = '/'; +#endif + typedef std::basic_string string_type; + + // constructors and destructor + + path() noexcept { } + + path(const path& __p) = default; + + path(path&& __p) noexcept + : _M_pathname(std::move(__p._M_pathname)), _M_type(__p._M_type) + { + _M_split_cmpts(); + __p.clear(); + } + + template> + path(_Source const& __source) + : _M_pathname(_S_convert(_S_range_begin(__source), + _S_range_end(__source))) + { _M_split_cmpts(); } + + template> + path(_InputIterator __first, _InputIterator __last) + : _M_pathname(_S_convert(__first, __last)) + { _M_split_cmpts(); } + + template, + typename _Require2 = __value_type_is_char<_Source>> + path(_Source const& __source, const locale& __loc) + : _M_pathname(_S_convert_loc(_S_range_begin(__source), + _S_range_end(__source), __loc)) + { _M_split_cmpts(); } + + template, + typename _Require2 = __value_type_is_char<_InputIterator>> + path(_InputIterator __first, _InputIterator __last, const locale& __loc) + : _M_pathname(_S_convert_loc(__first, __last, __loc)) + { _M_split_cmpts(); } + + ~path() = default; + + // assignments + + path& operator=(const path& __p) = default; + path& operator=(path&& __p) noexcept; + + template + _Path<_Source>& + operator=(_Source const& __source) + { return *this = path(__source); } + + template + _Path<_Source>& + assign(_Source const& __source) + { return *this = path(__source); } + + template + _Path<_InputIterator, _InputIterator>& + assign(_InputIterator __first, _InputIterator __last) + { return *this = path(__first, __last); } + + // appends + + path& operator/=(const path& __p) { return _M_append(__p._M_pathname); } + + template + _Path<_Source>& + operator/=(_Source const& __source) + { return append(__source); } + + template + _Path<_Source>& + append(_Source const& __source) + { + return _M_append(_S_convert(_S_range_begin(__source), + _S_range_end(__source))); + } + + template + _Path<_InputIterator, _InputIterator>& + append(_InputIterator __first, _InputIterator __last) + { return _M_append(_S_convert(__first, __last)); } + + // concatenation + + path& operator+=(const path& __x); + path& operator+=(const string_type& __x); + path& operator+=(const value_type* __x); + path& operator+=(value_type __x); + + template + _Path<_Source>& + operator+=(_Source const& __x) { return concat(__x); } + + template + _Path<_CharT*, _CharT*>& + operator+=(_CharT __x); + + template + _Path<_Source>& + concat(_Source const& __x) + { return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); } + + template + _Path<_InputIterator, _InputIterator>& + concat(_InputIterator __first, _InputIterator __last) + { return *this += _S_convert(__first, __last); } + + // modifiers + + void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); } + + path& make_preferred(); + path& remove_filename(); + path& replace_filename(const path& __replacement); + path& replace_extension(const path& __replacement = path()); + + void swap(path& __rhs) noexcept; + + // native format observers + + const string_type& native() const noexcept { return _M_pathname; } + const value_type* c_str() const noexcept { return _M_pathname.c_str(); } + operator string_type() const { return _M_pathname; } + + template, + typename _Allocator = std::allocator<_CharT>> + std::basic_string<_CharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const; + + std::string string() const; + std::wstring wstring() const; + std::string u8string() const; + std::u16string u16string() const; + std::u32string u32string() const; + + // generic format observers + template, + typename _Allocator = std::allocator<_CharT>> + std::basic_string<_CharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const; + + std::string generic_string() const; + std::wstring generic_wstring() const; + std::string generic_u8string() const; + std::u16string generic_u16string() const; + std::u32string generic_u32string() const; + + // compare + + int compare(const path& __p) const noexcept; + int compare(const string_type& __s) const; + int compare(const value_type* __s) const; + + // decomposition + + 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; + + // query + + bool empty() const noexcept { return _M_pathname.empty(); } + bool has_root_name() const; + bool has_root_directory() const; + bool has_root_path() 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 { return !is_absolute(); } + + // iterators + class iterator; + typedef iterator const_iterator; + + iterator begin() const; + iterator end() const; + + private: + enum class _Type : unsigned char { + _Multi, _Root_name, _Root_dir, _Filename + }; + + path(string_type __str, _Type __type) : _M_pathname(__str), _M_type(__type) + { + _GLIBCXX_DEBUG_ASSERT(!empty()); + _GLIBCXX_DEBUG_ASSERT(_M_type != _Type::_Multi); + } + + enum class _Split { _Stem, _Extension }; + + path& _M_append(const string_type& __str) + { + if (!_M_pathname.empty() && !_S_is_dir_sep(_M_pathname.back()) + && !__str.empty() && !_S_is_dir_sep(__str.front())) + _M_pathname += preferred_separator; + _M_pathname += __str; + _M_split_cmpts(); + return *this; + } + + pair _M_find_extension() const; + + template + struct _Cvt; + + static string_type + _S_convert(value_type* __src, __null_terminated) + { return string_type(__src); } + + static string_type + _S_convert(const value_type* __src, __null_terminated) + { return string_type(__src); } + + template + static string_type + _S_convert(_Iter __first, _Iter __last) + { + using __value_type = typename std::iterator_traits<_Iter>::value_type; + return _Cvt<__value_type>::_S_convert(__first, __last); + } + + template + static string_type + _S_convert(_InputIterator __src, __null_terminated) + { + using _Tp = typename std::iterator_traits<_InputIterator>::value_type; + std::basic_string<_Tp> __tmp; + while (*__src != _Tp{}) + __tmp.push_back(*__src++); + return _S_convert(__tmp.data(), __tmp.data() + __tmp.size()); + } + + static string_type + _S_convert_loc(const char* __first, const char* __last, + const std::locale& __loc); + + template + static string_type + _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc) + { + const std::string __str(__first, __last); + return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc); + } + + template + static string_type + _S_convert_loc(_InputIterator __src, __null_terminated, + const std::locale& __loc) + { + std::string __tmp; + while (*__src != '\0') + __tmp.push_back(*__src++); + return _S_convert_loc(__tmp.data(), __tmp.data()+__tmp.size(), __loc); + } + + bool _S_is_dir_sep(value_type __ch) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return __ch == L'/' || __ch == preferred_separator; +#else + return __ch == '/'; +#endif + } + + void _M_split_cmpts(); + void _M_trim(); + void _M_add_root_name(size_t n); + void _M_add_root_dir(size_t pos); + void _M_add_filename(size_t pos, size_t n); + + string_type _M_pathname; + + struct _Cmpt; + using _List = std::list<_Cmpt>; + _List _M_cmpts; // empty unless _M_type == _Type::_Multi + _Type _M_type = _Type::_Multi; + }; + + inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } + + size_t hash_value(const path& __p) noexcept; + + /// Compare paths + inline bool operator<(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs) < 0; } + + /// Compare paths + inline bool operator<=(const path& __lhs, const path& __rhs) noexcept + { return !(__rhs < __lhs); } + + /// Compare paths + inline bool operator>(const path& __lhs, const path& __rhs) noexcept + { return __rhs < __lhs; } + + /// Compare paths + inline bool operator>=(const path& __lhs, const path& __rhs) noexcept + { return !(__lhs < __rhs); } + + /// Compare paths + inline bool operator==(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs) == 0; } + + /// Compare paths + inline bool operator!=(const path& __lhs, const path& __rhs) noexcept + { return !(__lhs == __rhs); } + + /// Append one path to another + inline path operator/(const path& __lhs, const path& __rhs) + { return path(__lhs) /= __rhs; } + + /// Write a path to a stream + template + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) + { + auto __tmp = __p.string<_CharT, _Traits>(); + using __quoted_string + = std::__detail::_Quoted_string; + __os << __quoted_string{__tmp, '"', '\\'}; + return __os; + } + + /// Read a path from a stream + template + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) + { + basic_string<_CharT, _Traits> __tmp; + using __quoted_string + = std::__detail::_Quoted_string; + if (__is >> __quoted_string{ __tmp, '"', '\\' }) + __p = std::move(__tmp); + return __is; + } + + // TODO constrain with _Path and __value_type_is_char + template + inline path + u8path(const _Source& __source) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return path{ path::string_type{__source} }; +#else + return path{ __source }; +#endif + } + + // TODO constrain with _Path and __value_type_is_char + template + inline path + u8path(_InputIterator __first, _InputIterator __last) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return path{ path::string_type{__first, __last} }; +#else + return path{ __first, __last }; +#endif + } + + class filesystem_error : public std::system_error + { + public: + filesystem_error(const string& __what_arg, error_code __ec) + : system_error(__ec, __what_arg) { } + + filesystem_error(const string& __what_arg, const path& __p1, + error_code __ec) + : system_error(__ec, __what_arg), _M_path1(__p1) { } + + filesystem_error(const string& __what_arg, const path& __p1, + const path& __p2, error_code __ec) + : system_error(__ec, __what_arg), _M_path1(__p1), _M_path2(__p2) + { } + + const path& path1() const noexcept { return _M_path1; } + const path& path2() const noexcept { return _M_path2; } + const char* what() const noexcept { return _M_what.c_str(); } + + private: + std::string _M_gen_what(); + + path _M_path1; + path _M_path2; + std::string _M_what = _M_gen_what(); + }; + + struct path::_Cmpt : path + { + _Cmpt(string_type __s, _Type __t, size_t __pos) + : path(std::move(__s), __t), _M_pos(__pos) { } + + _Cmpt() : _M_pos(-1) { } + + size_t _M_pos; + }; + + template<> + struct path::__is_encoded_char : std::true_type + { using value_type = char; }; + + template<> + struct path::__is_encoded_char : std::true_type + { using value_type = wchar_t; }; + + template<> + struct path::__is_encoded_char : std::true_type + { using value_type = char16_t; }; + + template<> + struct path::__is_encoded_char : std::true_type + { using value_type = char32_t; }; + + // specialize _Cvt for degenerate 'noconv' case + template<> + struct path::_Cvt + { + template + static string_type + _S_convert(_Iter __first, _Iter __last) + { return string_type{__first, __last}; } + }; + + template + struct path::_Cvt + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + static string_type + _S_wconvert(const char* __f, const char* __l, true_type) + { + using _Cvt = std::codecvt; + const auto& __cvt = std::use_facet<_Cvt>(std::locale{}); + std::wstring __wstr; + if (__str_codecvt_in(__f, __l, __wstr, __cvt)) + return __wstr; + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } + + static string_type + _S_wconvert(const _CharT* __f, const _CharT* __l, false_type) + { + std::codecvt_utf8<_CharT> __cvt; + std::string __str; + if (__str_codecvt_out(__f, __l, __str, __cvt)) + { + const char* __f2 = __str.data(); + const char* __l2 = __f2 + __str.size(); + std::codecvt_utf8 __wcvt; + std::wstring __wstr; + if (__str_codecvt_in(__f2, __l2, __wstr, __wcvt)) + return __wstr; + } + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } + + static string_type + _S_convert(const _CharT* __f, const _CharT* __l) + { + return _S_wconvert(__f, __l, is_same<_CharT, char>{}); + } +#else + static string_type + _S_convert(const _CharT* __f, const _CharT* __l) + { + std::codecvt_utf8<_CharT> __cvt; + std::string __str; + if (__str_codecvt_out(__f, __l, __str, __cvt)) + return __str; + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } +#endif + + static string_type + _S_convert(_CharT* __f, _CharT* __l) + { + return _S_convert(const_cast(__f), + const_cast(__l)); + } + + template + static string_type + _S_convert(_Iter __first, _Iter __last) + { + const std::basic_string<_CharT> __str(__first, __last); + return _S_convert(__str.data(), __str.data() + __str.size()); + } + + template + static string_type + _S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first, + __gnu_cxx::__normal_iterator<_Iter, _Cont> __last) + { return _S_convert(__first.base(), __last.base()); } + }; + + /// An iterator for the components of a path + class path::iterator + { + public: + using difference_type = std::ptrdiff_t; + using value_type = path; + using reference = const path&; + using pointer = const path*; + using iterator_category = std::bidirectional_iterator_tag; + + iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { } + + iterator(const iterator&) = default; + iterator& operator=(const iterator&) = default; + + reference operator*() const; + pointer operator->() const { return std::__addressof(**this); } + + iterator& operator++(); + iterator operator++(int) { auto __tmp = *this; ++_M_cur; return __tmp; } + + iterator& operator--(); + iterator operator--(int) { auto __tmp = *this; --_M_cur; return __tmp; } + + friend bool operator==(const iterator& __lhs, const iterator& __rhs) + { return __lhs.equals(__rhs); } + + friend bool operator!=(const iterator& __lhs, const iterator& __rhs) + { return !__lhs.equals(__rhs); } + + private: + friend class path; + + iterator(const path* __path, path::_List::const_iterator __iter) + : _M_path(__path), _M_cur(__iter), _M_at_end() + { } + + iterator(const path* __path, bool __at_end) + : _M_path(__path), _M_cur(), _M_at_end(__at_end) + { } + + bool equals(iterator) const; + + const path* _M_path; + path::_List::const_iterator _M_cur; + bool _M_at_end; // only used when type != _Multi + }; + + + inline path& + path::operator=(path&& __p) noexcept + { + _M_pathname = std::move(__p._M_pathname); + _M_cmpts = std::move(__p._M_cmpts); + _M_type = __p._M_type; + __p.clear(); + return *this; + } + + inline path& + path::operator+=(const path& __p) + { + return operator+=(__p.native()); + } + + inline path& + path::operator+=(const string_type& __x) + { + _M_pathname += __x; + _M_split_cmpts(); + return *this; + } + + inline path& + path::operator+=(const value_type* __x) + { + _M_pathname += __x; + _M_split_cmpts(); + return *this; + } + + inline path& + path::operator+=(value_type __x) + { + _M_pathname += __x; + _M_split_cmpts(); + return *this; + } + + template + inline path::_Path<_CharT*, _CharT*>& + path::operator+=(_CharT __x) + { + auto* __addr = std::addressof(__x); + return concat(__addr, __addr + 1); + } + + inline path& + path::make_preferred() + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + std::replace(_M_pathname.begin(), _M_pathname.end(), L'/', + preferred_separator); +#endif + return *this; + } + + inline void path::swap(path& __rhs) noexcept + { + _M_pathname.swap(__rhs._M_pathname); + _M_cmpts.swap(__rhs._M_cmpts); + std::swap(_M_type, __rhs._M_type); + } + + template + inline std::basic_string<_CharT, _Traits, _Allocator> + path::string(const _Allocator& __a) const + { + if (is_same<_CharT, value_type>::value) + return { _M_pathname.begin(), _M_pathname.end(), __a }; + + const value_type* __first = _M_pathname.data(); + const value_type* __last = __first + _M_pathname.size(); + +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + using _CharAlloc = typename __alloc_rebind<_Allocator, char>; + using _String = basic_string, _CharAlloc>; + using _WString = basic_string<_CharT, _Traits, _Allocator>; + + // use codecvt_utf8 to convert native string to UTF-8 + codecvt_utf8 __cvt; + _String __u8str{_CharAlloc{__a}}; + if (__str_codecvt_out(__first, __last, __u8str, __cvt)) + { + struct + { + const _String* + operator()(const _String& __from, _String&, true_type) + { return std::__addressof(__from); } + + _WString* + operator()(const _String& __from, _WString& __to, false_type) + { + // use codecvt_utf8<_CharT> to convert UTF-8 to wide string + codecvt_utf8<_CharT> __cvt; + const char* __f = __from.data(); + const char* __l = __f + __from.size(); + if (__str_codecvt_in(__f, __l, __to, __cvt)) + return std::__addressof(__to); + return nullptr; + } + } __dispatch; + _WString __wstr; + if (auto* __p = __dispatch(__u8str, __wstr, is_same<_CharT, char>{})) + return *__p; + } +#else + codecvt_utf8<_CharT> __cvt; + basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; + if (__str_codecvt_in(__first, __last, __wstr, __cvt)) + return __wstr; +#endif + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } + + inline std::string + path::string() const { return string(); } + + inline std::wstring + path::wstring() const { return string(); } + + inline std::string + path::u8string() const + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + std::string __str; + // convert from native encoding to UTF-8 + codecvt_utf8 __cvt; + const value_type* __first = _M_pathname.data(); + const value_type* __last = __first + _M_pathname.size(); + if (__str_codecvt_out(__first, __last, __str, __cvt)) + return __str; + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); +#else + return _M_pathname; +#endif + } + + inline std::u16string + path::u16string() const { return string(); } + + inline std::u32string + path::u32string() const { return string(); } + +#ifndef _GLIBCXX_FILESYSTEM_IS_WINDOWS + template + inline std::basic_string<_CharT, _Traits, _Allocator> + path::generic_string(const _Allocator& __a) const + { return string<_CharT, _Traits, _Allocator>(__a); } + + inline std::string + path::generic_string() const { return string(); } + + inline std::wstring + path::generic_wstring() const { return wstring(); } + + inline std::string + path::generic_u8string() const { return u8string(); } + + inline std::u16string + path::generic_u16string() const { return u16string(); } + + inline std::u32string + path::generic_u32string() const { return u32string(); } +#endif + + inline int + path::compare(const string_type& __s) const { return compare(path(__s)); } + + inline int + path::compare(const value_type* __s) const { return compare(path(__s)); } + + inline path + path::filename() const { return empty() ? path() : *--end(); } + + inline path + path::stem() const + { + auto ext = _M_find_extension(); + if (ext.first && ext.second != 0) + return path{ext.first->substr(0, ext.second)}; + return {}; + } + + inline path + path::extension() const + { + auto ext = _M_find_extension(); + if (ext.first && ext.second != string_type::npos) + return path{ext.first->substr(ext.second)}; + return {}; + } + + inline bool + path::has_stem() const + { + auto ext = _M_find_extension(); + return ext.first && ext.second != 0; + } + + inline bool + path::has_extension() const + { + auto ext = _M_find_extension(); + return ext.first && ext.second != string_type::npos; + } + + inline bool + path::is_absolute() const + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return has_root_name(); +#else + return has_root_directory(); +#endif + } + + inline path::iterator + path::begin() const + { + if (_M_type == _Type::_Multi) + return iterator(this, _M_cmpts.begin()); + return iterator(this, false); + } + + inline path::iterator + path::end() const + { + if (_M_type == _Type::_Multi) + return iterator(this, _M_cmpts.end()); + return iterator(this, true); + } + + inline path::iterator& + path::iterator::operator++() + { + _GLIBCXX_DEBUG_ASSERT(_M_path != nullptr); + if (_M_path->_M_type == _Type::_Multi) + { + _GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.end()); + ++_M_cur; + } + else + { + _GLIBCXX_DEBUG_ASSERT(!_M_at_end); + _M_at_end = true; + } + return *this; + } + + inline path::iterator& + path::iterator::operator--() + { + _GLIBCXX_DEBUG_ASSERT(_M_path != nullptr); + if (_M_path->_M_type == _Type::_Multi) + { + _GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.begin()); + --_M_cur; + } + else + { + _GLIBCXX_DEBUG_ASSERT(_M_at_end); + _M_at_end = false; + } + return *this; + } + + inline path::iterator::reference + path::iterator::operator*() const + { + _GLIBCXX_DEBUG_ASSERT(_M_path != nullptr); + if (_M_path->_M_type == _Type::_Multi) + { + _GLIBCXX_DEBUG_ASSERT(_M_cur != _M_path->_M_cmpts.end()); + return *_M_cur; + } + return *_M_path; + } + + inline bool + path::iterator::equals(iterator __rhs) const + { + if (_M_path != __rhs._M_path) + return false; + if (_M_path == nullptr) + return true; + if (_M_path->_M_type == path::_Type::_Multi) + return _M_cur == __rhs._M_cur; + return _M_at_end == __rhs._M_at_end; + } + + // @} group filesystem +_GLIBCXX_END_NAMESPACE_CXX11 +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace v1 +} // namespace filesystem +} // namespace experimental +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_EXPERIMENTAL_FS_PATH_H diff --git a/libstdc++-v3/include/std/iomanip b/libstdc++-v3/include/std/iomanip index 049ea0ca1b7..38f8c9d82ef 100644 --- a/libstdc++-v3/include/std/iomanip +++ b/libstdc++-v3/include/std/iomanip @@ -42,7 +42,7 @@ #if __cplusplus >= 201103L #include #if __cplusplus > 201103L -#include // used in quoted. +#include #endif #endif @@ -450,127 +450,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define __cpp_lib_quoted_string_io 201304 -_GLIBCXX_END_NAMESPACE_VERSION - namespace __detail { - _GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief Struct for delimited strings. - */ - template - struct _Quoted_string - { - static_assert(is_reference<_String>::value - || is_pointer<_String>::value, - "String type must be pointer or reference"); - - _Quoted_string(_String __str, _CharT __del, _CharT __esc) - : _M_string(__str), _M_delim{__del}, _M_escape{__esc} - { } - - _Quoted_string& - operator=(_Quoted_string&) = delete; - - _String _M_string; - _CharT _M_delim; - _CharT _M_escape; - }; - - /** - * @brief Inserter for quoted strings. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 2344 quoted()'s interaction with padding is unclear - */ - template - auto& - operator<<(std::basic_ostream<_CharT, _Traits>& __os, - const _Quoted_string& __str) - { - std::basic_ostringstream<_CharT, _Traits> __ostr; - __ostr << __str._M_delim; - for (const _CharT* __c = __str._M_string; *__c; ++__c) - { - if (*__c == __str._M_delim || *__c == __str._M_escape) - __ostr << __str._M_escape; - __ostr << *__c; - } - __ostr << __str._M_delim; - - return __os << __ostr.str(); - } - - /** - * @brief Inserter for quoted strings. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 2344 quoted()'s interaction with padding is unclear - */ - template - auto& - operator<<(std::basic_ostream<_CharT, _Traits>& __os, - const _Quoted_string<_String, _CharT>& __str) - { - std::basic_ostringstream<_CharT, _Traits> __ostr; - __ostr << __str._M_delim; - for (auto& __c : __str._M_string) - { - if (__c == __str._M_delim || __c == __str._M_escape) - __ostr << __str._M_escape; - __ostr << __c; - } - __ostr << __str._M_delim; - - return __os << __ostr.str(); - } - - /** - * @brief Extractor for delimited strings. - * The left and right delimiters can be different. - */ - template - auto& - operator>>(std::basic_istream<_CharT, _Traits>& __is, - const _Quoted_string&, - _CharT>& __str) - { - _CharT __c; - __is >> __c; - if (!__is.good()) - return __is; - if (__c != __str._M_delim) - { - __is.unget(); - __is >> __str._M_string; - return __is; - } - __str._M_string.clear(); - std::ios_base::fmtflags __flags - = __is.flags(__is.flags() & ~std::ios_base::skipws); - do - { - __is >> __c; - if (!__is.good()) - break; - if (__c == __str._M_escape) - { - __is >> __c; - if (!__is.good()) - break; - } - else if (__c == __str._M_delim) - break; - __str._M_string += __c; - } - while (true); - __is.setf(__flags); - - return __is; - } - _GLIBCXX_END_NAMESPACE_VERSION - } // namespace __detail -_GLIBCXX_BEGIN_NAMESPACE_VERSION - /** * @brief Manipulator for quoted strings. * @param __string String to quote. diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 5a414c59a7a..37c3b9bf297 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -979,6 +979,22 @@ class StdExpStringViewPrinter: def display_hint (self): return 'string' +class StdExpPathPrinter: + "Print a std::experimental::filesystem::path" + + def __init__ (self, typename, val): + self.val = val + self.list_visualizer = gdb.default_visualizer(val['_M_cmpts']) + + def to_string (self): + path = self.val ['_M_pathname'] + if self.list_visualizer: + list_head = self.val['_M_cmpts']['_M_impl']['_M_node'] + if list_head.address != list_head['_M_next']: + cmpts = self.list_visualizer.to_string() + path = "%s [Components %s]" % (path, cmpts) + return path + # A "regular expression" printer which conforms to the # "SubPrettyPrinter" protocol from gdb.printing. class RxPrinter(object): @@ -1364,6 +1380,11 @@ def build_libstdcxx_dictionary (): 'optional', StdExpOptionalPrinter) libstdcxx_printer.add_version('std::experimental::fundamentals_v1::', 'basic_string_view', StdExpStringViewPrinter) + # Filesystem TS components + libstdcxx_printer.add_version('std::experimental::filesystem::v1::', + 'path', StdExpPathPrinter) + libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11', + 'path', StdExpPathPrinter) # Extensions. libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter) diff --git a/libstdc++-v3/scripts/testsuite_flags.in b/libstdc++-v3/scripts/testsuite_flags.in index 5e7ad328090..ee5916787b1 100755 --- a/libstdc++-v3/scripts/testsuite_flags.in +++ b/libstdc++-v3/scripts/testsuite_flags.in @@ -77,7 +77,8 @@ case ${query} in echo ${PCHFLAGS} ;; --cxxldflags) - SECTIONLDFLAGS="@SECTION_LDFLAGS@ @LIBICONV@" + SECTIONLDFLAGS="@SECTION_LDFLAGS@ @LIBICONV@ + -L${BUILD_DIR}/src/filesystem/.libs" echo ${SECTIONLDFLAGS} ;; *) diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am index debf967801f..a5f48b22c6d 100644 --- a/libstdc++-v3/src/Makefile.am +++ b/libstdc++-v3/src/Makefile.am @@ -22,7 +22,13 @@ include $(top_srcdir)/fragment.am -SUBDIRS = c++98 c++11 +if ENABLE_FILESYSTEM_TS +filesystem_dir = filesystem +else +filesystem_dir = +endif + +SUBDIRS = c++98 c++11 $(filesystem_dir) # Cross compiler support. if VTV_CYGMIN @@ -52,6 +58,9 @@ endif vpath % $(top_srcdir)/src/c++98 vpath % $(top_srcdir)/src/c++11 +if ENABLE_FILESYSTEM_TS +vpath % $(top_srcdir)/src/filesystem +endif if GLIBCXX_LDBL_COMPAT ldbl_compat_sources = compatibility-ldbl.cc diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index dd9ecd16381..433f9ea121a 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -123,7 +123,7 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) +DIST_SUBDIRS = c++98 c++11 filesystem ABI_TWEAKS_SRCDIR = @ABI_TWEAKS_SRCDIR@ ACLOCAL = @ACLOCAL@ ALLOCATOR_H = @ALLOCATOR_H@ @@ -346,7 +346,9 @@ WARN_CXXFLAGS = \ # -I/-D flags to pass when compiling. AM_CPPFLAGS = $(GLIBCXX_INCLUDES) -SUBDIRS = c++98 c++11 +@ENABLE_FILESYSTEM_TS_FALSE@filesystem_dir = +@ENABLE_FILESYSTEM_TS_TRUE@filesystem_dir = filesystem +SUBDIRS = c++98 c++11 $(filesystem_dir) @VTV_CYGMIN_FALSE@toolexeclib_LTLIBRARIES = libstdc++.la # Cross compiler support. @@ -859,6 +861,7 @@ uninstall-am: uninstall-toolexeclibLTLIBRARIES vpath % $(top_srcdir)/src/c++98 vpath % $(top_srcdir)/src/c++11 +@ENABLE_FILESYSTEM_TS_TRUE@vpath % $(top_srcdir)/src/filesystem # Use special rules for compatibility-ldbl.cc compilation, as we need to # pass -mlong-double-64. diff --git a/libstdc++-v3/src/filesystem/Makefile.am b/libstdc++-v3/src/filesystem/Makefile.am new file mode 100644 index 00000000000..c6e06c87a6b --- /dev/null +++ b/libstdc++-v3/src/filesystem/Makefile.am @@ -0,0 +1,100 @@ +## Makefile for the GNU C++ Filesystem library. +## +## Copyright (C) 2014 Free Software Foundation, Inc. +## +## Process this file with automake to produce Makefile.in. +## +## This file is part of GCC. +## +## GCC is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3, or (at your option) +## any later version. +## +## GCC is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with GCC; see the file COPYING3. If not see +## . + +include $(top_srcdir)/fragment.am + +toolexeclib_LTLIBRARIES = libstdc++fs.la + +headers = + +sources = \ + dir.cc \ + ops.cc \ + path.cc + +# vpath % $(top_srcdir)/src/filesystem + +libstdc__fs_la_SOURCES = $(sources) + +# AM_CXXFLAGS needs to be in each subdirectory so that it can be +# modified in a per-library or per-sub-library way. Need to manually +# set this option because CONFIG_CXXFLAGS has to be after +# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden +# as the occasion call for it. +AM_CXXFLAGS = \ + $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ + -std=gnu++14 \ + $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) + +AM_MAKEFLAGS = \ + "gxx_include_dir=$(gxx_include_dir)" + + +# Libtool notes + +# 1) In general, libtool expects an argument such as `--tag=CXX' when +# using the C++ compiler, because that will enable the settings +# detected when C++ support was being configured. However, when no +# such flag is given in the command line, libtool attempts to figure +# it out by matching the compiler name in each configuration section +# against a prefix of the command line. The problem is that, if the +# compiler name and its initial flags stored in the libtool +# configuration file don't match those in the command line, libtool +# can't decide which configuration to use, and it gives up. The +# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe +# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to +# attempt to infer which configuration to use. +# +# The second tag argument, `--tag disable-shared` means that libtool +# only compiles each source once, for static objects. In actuality, +# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to +# the libtool command that is used create the object, which is +# suitable for shared libraries. The `--tag disable-shared` must be +# placed after --tag CXX lest things CXX undo the affect of +# disable-shared. + +# 2) Need to explicitly set LTCXXCOMPILE so that EXTRA_CXX_FLAGS is +# last. (That way, things like -O2 passed down from the toplevel can +# be overridden by --enable-debug.) +LTCXXCOMPILE = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(TOPLEVEL_INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(EXTRA_CXX_FLAGS) + +LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) + +# 3) We'd have a problem when building the shared libstdc++ object if +# the rules automake generates would be used. We cannot allow g++ to +# be used since this would add -lstdc++ to the link line which of +# course is problematic at this point. So, we get the top-level +# directory to configure libstdc++-v3 to use gcc as the C++ +# compilation driver. +CXXLINK = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXX) \ + $(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@ + +# By adding these files here, automake will remove them for 'make clean' +CLEANFILES = stamp-* + diff --git a/libstdc++-v3/src/filesystem/Makefile.in b/libstdc++-v3/src/filesystem/Makefile.in new file mode 100644 index 00000000000..1ff2d72d0d1 --- /dev/null +++ b/libstdc++-v3/src/filesystem/Makefile.in @@ -0,0 +1,661 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(top_srcdir)/fragment.am $(srcdir)/Makefile.in \ + $(srcdir)/Makefile.am +subdir = src/filesystem +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ + $(top_srcdir)/../config/enable.m4 \ + $(top_srcdir)/../config/futex.m4 \ + $(top_srcdir)/../config/iconv.m4 \ + $(top_srcdir)/../config/lead-dot.m4 \ + $(top_srcdir)/../config/lib-ld.m4 \ + $(top_srcdir)/../config/lib-link.m4 \ + $(top_srcdir)/../config/lib-prefix.m4 \ + $(top_srcdir)/../config/lthostflags.m4 \ + $(top_srcdir)/../config/multi.m4 \ + $(top_srcdir)/../config/no-executables.m4 \ + $(top_srcdir)/../config/override.m4 \ + $(top_srcdir)/../config/stdint.m4 \ + $(top_srcdir)/../config/unwind_ipinfo.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ + $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ + $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/crossconfig.m4 \ + $(top_srcdir)/linkage.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../config/gc++filt.m4 \ + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../config/gthr.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(toolexeclibdir)" +LTLIBRARIES = $(toolexeclib_LTLIBRARIES) +libstdc__fs_la_LIBADD = +am__objects_1 = dir.lo ops.lo path.lo +am_libstdc__fs_la_OBJECTS = $(am__objects_1) +libstdc__fs_la_OBJECTS = $(am_libstdc__fs_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = +am__depfiles_maybe = +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +SOURCES = $(libstdc__fs_la_SOURCES) +ETAGS = etags +CTAGS = ctags +ABI_TWEAKS_SRCDIR = @ABI_TWEAKS_SRCDIR@ +ACLOCAL = @ACLOCAL@ +ALLOCATOR_H = @ALLOCATOR_H@ +ALLOCATOR_NAME = @ALLOCATOR_NAME@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ATOMICITY_SRCDIR = @ATOMICITY_SRCDIR@ +ATOMIC_FLAGS = @ATOMIC_FLAGS@ +ATOMIC_WORD_SRCDIR = @ATOMIC_WORD_SRCDIR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BASIC_FILE_CC = @BASIC_FILE_CC@ +BASIC_FILE_H = @BASIC_FILE_H@ +CC = @CC@ +CCODECVT_CC = @CCODECVT_CC@ +CCOLLATE_CC = @CCOLLATE_CC@ +CCTYPE_CC = @CCTYPE_CC@ +CFLAGS = @CFLAGS@ +CLOCALE_CC = @CLOCALE_CC@ +CLOCALE_H = @CLOCALE_H@ +CLOCALE_INTERNAL_H = @CLOCALE_INTERNAL_H@ +CMESSAGES_CC = @CMESSAGES_CC@ +CMESSAGES_H = @CMESSAGES_H@ +CMONEY_CC = @CMONEY_CC@ +CNUMERIC_CC = @CNUMERIC_CC@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPU_DEFINES_SRCDIR = @CPU_DEFINES_SRCDIR@ +CPU_OPT_BITS_RANDOM = @CPU_OPT_BITS_RANDOM@ +CPU_OPT_EXT_RANDOM = @CPU_OPT_EXT_RANDOM@ +CSTDIO_H = @CSTDIO_H@ +CTIME_CC = @CTIME_CC@ +CTIME_H = @CTIME_H@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXFILT = @CXXFILT@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +C_INCLUDE_DIR = @C_INCLUDE_DIR@ +DBLATEX = @DBLATEX@ +DEBUG_FLAGS = @DEBUG_FLAGS@ +DEFS = @DEFS@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ +EXEEXT = @EXEEXT@ +EXTRA_CXX_FLAGS = @EXTRA_CXX_FLAGS@ +FGREP = @FGREP@ +GLIBCXX_INCLUDES = @GLIBCXX_INCLUDES@ +GLIBCXX_LIBS = @GLIBCXX_LIBS@ +GREP = @GREP@ +HWCAP_FLAGS = @HWCAP_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPTIMIZE_CXXFLAGS = @OPTIMIZE_CXXFLAGS@ +OPT_LDFLAGS = @OPT_LDFLAGS@ +OS_INC_SRCDIR = @OS_INC_SRCDIR@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PDFLATEX = @PDFLATEX@ +RANLIB = @RANLIB@ +SECTION_FLAGS = @SECTION_FLAGS@ +SECTION_LDFLAGS = @SECTION_LDFLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYMVER_FILE = @SYMVER_FILE@ +TOPLEVEL_INCLUDES = @TOPLEVEL_INCLUDES@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +VTV_CXXFLAGS = @VTV_CXXFLAGS@ +VTV_CXXLINKFLAGS = @VTV_CXXLINKFLAGS@ +VTV_PCH_CXXFLAGS = @VTV_PCH_CXXFLAGS@ +WARN_FLAGS = @WARN_FLAGS@ +WERROR = @WERROR@ +XMLLINT = @XMLLINT@ +XSLTPROC = @XSLTPROC@ +XSL_STYLE_DIR = @XSL_STYLE_DIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +baseline_dir = @baseline_dir@ +baseline_subdir_switch = @baseline_subdir_switch@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +check_msgfmt = @check_msgfmt@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ +exec_prefix = @exec_prefix@ +glibcxx_MOFILES = @glibcxx_MOFILES@ +glibcxx_PCHFLAGS = @glibcxx_PCHFLAGS@ +glibcxx_POFILES = @glibcxx_POFILES@ +glibcxx_builddir = @glibcxx_builddir@ +glibcxx_compiler_pic_flag = @glibcxx_compiler_pic_flag@ +glibcxx_compiler_shared_flag = @glibcxx_compiler_shared_flag@ +glibcxx_cxx98_abi = @glibcxx_cxx98_abi@ +glibcxx_localedir = @glibcxx_localedir@ +glibcxx_lt_pic_flag = @glibcxx_lt_pic_flag@ +glibcxx_prefixdir = @glibcxx_prefixdir@ +glibcxx_srcdir = @glibcxx_srcdir@ +glibcxx_toolexecdir = @glibcxx_toolexecdir@ +glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@ +gxx_include_dir = @gxx_include_dir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libtool_VERSION = @libtool_VERSION@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_host_flags = @lt_host_flags@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +multi_basedir = @multi_basedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +port_specific_symbol_files = @port_specific_symbol_files@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +python_mod_dir = @python_mod_dir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +thread_header = @thread_header@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +toplevel_builddir = @toplevel_builddir@ +toplevel_srcdir = @toplevel_srcdir@ + +# May be used by various substitution variables. +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) +MAINT_CHARSET = latin1 +mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs +PWD_COMMAND = $${PWDCMD-pwd} +STAMP = echo timestamp > +toolexecdir = $(glibcxx_toolexecdir) +toolexeclibdir = $(glibcxx_toolexeclibdir) +@ENABLE_WERROR_FALSE@WERROR_FLAG = +@ENABLE_WERROR_TRUE@WERROR_FLAG = $(WERROR) +@ENABLE_EXTERN_TEMPLATE_FALSE@XTEMPLATE_FLAGS = +@ENABLE_EXTERN_TEMPLATE_TRUE@XTEMPLATE_FLAGS = -fno-implicit-templates + +# These bits are all figured out from configure. Look in acinclude.m4 +# or configure.ac to see how they are set. See GLIBCXX_EXPORT_FLAGS. +CONFIG_CXXFLAGS = \ + $(SECTION_FLAGS) $(HWCAP_FLAGS) -frandom-seed=$@ + +WARN_CXXFLAGS = \ + $(WARN_FLAGS) $(WERROR_FLAG) -fdiagnostics-show-location=once + + +# -I/-D flags to pass when compiling. +AM_CPPFLAGS = $(GLIBCXX_INCLUDES) +toolexeclib_LTLIBRARIES = libstdc++fs.la +headers = +sources = \ + dir.cc \ + ops.cc \ + path.cc + + +# vpath % $(top_srcdir)/src/filesystem +libstdc__fs_la_SOURCES = $(sources) + +# AM_CXXFLAGS needs to be in each subdirectory so that it can be +# modified in a per-library or per-sub-library way. Need to manually +# set this option because CONFIG_CXXFLAGS has to be after +# OPTIMIZE_CXXFLAGS on the compile line so that -O2 can be overridden +# as the occasion call for it. +AM_CXXFLAGS = \ + $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ + -std=gnu++14 \ + $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) + +AM_MAKEFLAGS = \ + "gxx_include_dir=$(gxx_include_dir)" + + +# Libtool notes + +# 1) In general, libtool expects an argument such as `--tag=CXX' when +# using the C++ compiler, because that will enable the settings +# detected when C++ support was being configured. However, when no +# such flag is given in the command line, libtool attempts to figure +# it out by matching the compiler name in each configuration section +# against a prefix of the command line. The problem is that, if the +# compiler name and its initial flags stored in the libtool +# configuration file don't match those in the command line, libtool +# can't decide which configuration to use, and it gives up. The +# correct solution is to add `--tag CXX' to LTCXXCOMPILE and maybe +# CXXLINK, just after $(LIBTOOL), so that libtool doesn't have to +# attempt to infer which configuration to use. +# +# The second tag argument, `--tag disable-shared` means that libtool +# only compiles each source once, for static objects. In actuality, +# glibcxx_lt_pic_flag and glibcxx_compiler_shared_flag are added to +# the libtool command that is used create the object, which is +# suitable for shared libraries. The `--tag disable-shared` must be +# placed after --tag CXX lest things CXX undo the affect of +# disable-shared. + +# 2) Need to explicitly set LTCXXCOMPILE so that EXTRA_CXX_FLAGS is +# last. (That way, things like -O2 passed down from the toplevel can +# be overridden by --enable-debug.) +LTCXXCOMPILE = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(TOPLEVEL_INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(EXTRA_CXX_FLAGS) + +LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) + +# 3) We'd have a problem when building the shared libstdc++ object if +# the rules automake generates would be used. We cannot allow g++ to +# be used since this would add -lstdc++ to the link line which of +# course is problematic at this point. So, we get the top-level +# directory to configure libstdc++-v3 to use gcc as the C++ +# compilation driver. +CXXLINK = \ + $(LIBTOOL) --tag CXX --tag disable-shared \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXX) \ + $(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_CXXFLAGS) $(LTLDFLAGS) -o $@ + + +# By adding these files here, automake will remove them for 'make clean' +CLEANFILES = stamp-* +all: all-am + +.SUFFIXES: +.SUFFIXES: .cc .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/fragment.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps src/filesystem/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps src/filesystem/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" + @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \ + } + +uninstall-toolexeclibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \ + done + +clean-toolexeclibLTLIBRARIES: + -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES) + @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libstdc++fs.la: $(libstdc__fs_la_OBJECTS) $(libstdc__fs_la_DEPENDENCIES) + $(CXXLINK) -rpath $(toolexeclibdir) $(libstdc__fs_la_OBJECTS) $(libstdc__fs_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.cc.o: + $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: + $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: + $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(toolexeclibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-toolexeclibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-toolexeclibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-toolexeclibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-toolexeclibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-toolexeclibLTLIBRARIES installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-toolexeclibLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libstdc++-v3/src/filesystem/dir.cc b/libstdc++-v3/src/filesystem/dir.cc new file mode 100644 index 00000000000..4ed869ef783 --- /dev/null +++ b/libstdc++-v3/src/filesystem/dir.cc @@ -0,0 +1,396 @@ +// Class filesystem::directory_entry etc. -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include +#include +#include +#include +#include +#include +#ifdef _GLIBCXX_HAVE_DIRENT_H +# ifdef _GLIBCXX_HAVE_SYS_TYPES_H +# include +# endif +# include +#else +// TODO: replace dummy definitions with suitable Win32 code +#ifndef EACCES +# define EACCES static_cast(std::errc::permission_denied) +#endif +using DIR = void; +using P = std::experimental::filesystem::path; +static DIR* opendir(const P::value_type*) { return nullptr; } +static void closedir(DIR*) { } +struct dirent { const char* d_name; }; +static inline int readdir_r(DIR*, dirent*, dirent**) +{ return static_cast(std::errc::not_supported); } +#endif + +namespace fs = std::experimental::filesystem; + +namespace +{ + struct ErrorCode + { + ErrorCode(std::error_code* p) : ec(p) { } + + ErrorCode(ErrorCode&& e) : ec(std::exchange(e.ec, nullptr)) { } + + ~ErrorCode() { if (ec) ec->clear(); } + + void assign(int err) + { + ec->assign(err, std::generic_category()); + ec = nullptr; + } + + explicit operator bool() { return ec != nullptr; } + + std::error_code* ec; + }; +} + +struct fs::_Dir +{ + _Dir() : dirp(nullptr) { } + + _Dir(DIR* dirp, const fs::path& path) : dirp(dirp), path(path) { } + + _Dir(_Dir&& d) + : dirp(std::exchange(d.dirp, nullptr)), path(std::move(d.path)), + entry(std::move(d.entry)), type(d.type) + { } + + _Dir& operator=(_Dir&&) = delete; + + ~_Dir() { if (dirp) ::closedir(dirp); } + + bool advance(ErrorCode); + + DIR* dirp; + fs::path path; + directory_entry entry; + file_type type = file_type::none; +}; + +namespace +{ + template + bool is_set(Bitmask obj, Bitmask bits) + { + return (obj & bits) != Bitmask::none; + } + + fs::_Dir + opendir(const fs::path& p, fs::directory_options options, ErrorCode ec) + { + if (DIR* dirp = ::opendir(p.c_str())) + return {dirp, p}; + + const int err = errno; + if (err == EACCES + && is_set(options, fs::directory_options::skip_permission_denied)) + return {}; + + if (!ec) + _GLIBCXX_THROW_OR_ABORT(fs::filesystem_error( + "directory iterator cannot open directory", p, + std::error_code(err, std::generic_category()))); + + ec.assign(err); + return {}; + } + + inline std::shared_ptr + make_shared_dir(fs::_Dir&& dir) + { + if (dir.dirp) + return std::make_shared(std::move(dir)); + return {}; + } + + inline fs::file_type + get_file_type(const dirent& d __attribute__((__unused__))) + { +#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE + switch (d.d_type) + { + case DT_BLK: + return fs::file_type::block; + case DT_CHR: + return fs::file_type::character; + case DT_DIR: + return fs::file_type::directory; + case DT_FIFO: + return fs::file_type::fifo; + case DT_LNK: + return fs::file_type::symlink; + case DT_REG: + return fs::file_type::regular; + case DT_SOCK: + return fs::file_type::socket; + case DT_UNKNOWN: + return fs::file_type::unknown; + default: + return fs::file_type::none; + } +#else + return fs::file_type::none; +#endif + } +} + +bool +fs::_Dir::advance(ErrorCode ec) +{ + ::dirent ent; + ::dirent* result; + if (int err = readdir_r(dirp, &ent, &result)) + { + if (!ec) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "directory iterator cannot advance", + std::error_code(err, std::generic_category()))); + ec.assign(err); + return true; + } + else if (result != nullptr) + { + // skip past dot and dot-dot + if (!strcmp(ent.d_name, ".") || !strcmp(ent.d_name, "..")) + return advance(std::move(ec)); + entry = fs::directory_entry{path / ent.d_name}; + type = get_file_type(ent); + return true; + } + else + { + // reached the end + entry = {}; + type = fs::file_type::none; + return false; + } +} + +fs::directory_iterator:: +directory_iterator(const path& p, directory_options options, error_code* ec) +: directory_iterator(make_shared_dir(opendir(p, options, ec)), ec) +{ } + +fs::directory_iterator:: +directory_iterator(std::shared_ptr<_Dir> dir, error_code* ec) +: _M_dir(std::move(dir)) +{ + if (_M_dir && !_M_dir->advance(ec)) + _M_dir.reset(); +} + +const fs::directory_entry& +fs::directory_iterator::operator*() const +{ + if (!_M_dir) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "non-dereferenceable directory iterator", + std::make_error_code(errc::invalid_argument))); + return _M_dir->entry; +} + +fs::directory_iterator& +fs::directory_iterator::operator++() +{ + if (!_M_dir) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "cannot advance non-dereferenceable directory iterator", + std::make_error_code(errc::invalid_argument))); + if (!_M_dir->advance(nullptr)) + _M_dir.reset(); + return *this; +} + +fs::directory_iterator& +fs::directory_iterator::increment(error_code& ec) noexcept +{ + if (!_M_dir) + { + ec = std::make_error_code(errc::invalid_argument); + return *this; + } + if (!_M_dir->advance(&ec)) + _M_dir.reset(); + return *this; +} + +using Dir_iter_pair = std::pair; + +struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir> +{ + void clear() { c.clear(); } +}; + +fs::recursive_directory_iterator:: +recursive_directory_iterator(const path& p, directory_options options, + error_code* ec) +: _M_options(options), _M_pending(true) +{ + if (DIR* dirp = ::opendir(p.c_str())) + { + _M_dirs = std::make_shared<_Dir_stack>(); + _M_dirs->push(_Dir{ dirp, p }); + if (!_M_dirs->top().advance(ec)) + _M_dirs.reset(); + } + else + { + const int err = errno; + if (err == EACCES + && is_set(options, fs::directory_options::skip_permission_denied)) + return; + + if (!ec) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "recursive directory iterator cannot open directory", p, + std::error_code(err, std::generic_category()))); + + ec->assign(err, std::generic_category()); + } +} + +fs::recursive_directory_iterator::~recursive_directory_iterator() = default; + +int +fs::recursive_directory_iterator::depth() const +{ + return int(_M_dirs->size()) - 1; +} + +const fs::directory_entry& +fs::recursive_directory_iterator::operator*() const +{ + return _M_dirs->top().entry; +} + +fs::recursive_directory_iterator& +fs::recursive_directory_iterator:: +operator=(const recursive_directory_iterator& other) noexcept = default; + +fs::recursive_directory_iterator& +fs::recursive_directory_iterator:: +operator=(recursive_directory_iterator&& other) noexcept = default; + +fs::recursive_directory_iterator& +fs::recursive_directory_iterator::operator++() +{ + error_code ec; + increment(ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "cannot increment recursive directory iterator", ec)); + return *this; +} + +namespace +{ + bool + recurse(const fs::_Dir& d, fs::directory_options options, std::error_code& ec) + { + bool follow_symlink + = is_set(options, fs::directory_options::follow_directory_symlink); +#ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE + if (d.type == fs::file_type::directory) + return true; + if (d.type == fs::file_type::symlink && follow_symlink) + return d.entry.status().type() == fs::file_type::directory; + if (d.type != fs::file_type::none && d.type != fs::file_type::unknown) + return false; +#endif + const fs::path& path = d.entry.path(); + auto type = fs::symlink_status(path, ec).type(); + if (ec.value()) + return false; + if (type == fs::file_type::symlink) + { + if (!follow_symlink) + return false; + type = fs::status(path, ec).type(); + } + return type == fs::file_type::directory; + } +} + +fs::recursive_directory_iterator& +fs::recursive_directory_iterator::increment(error_code& ec) noexcept +{ + if (!_M_dirs) + { + ec = std::make_error_code(errc::invalid_argument); + return *this; + } + + auto& top = _M_dirs->top(); + + if (std::exchange(_M_pending, true) && recurse(top, _M_options, ec)) + { + _Dir dir = opendir(top.entry.path(), _M_options, &ec); + if (ec.value()) + return *this; + if (dir.dirp) + { + _M_dirs->push(std::move(dir)); + if (!_M_dirs->top().advance(&ec)) // dir is empty + pop(); + return *this; + } + // else skip permission denied and continue in parent dir + } + + ec.clear(); + while (!_M_dirs->top().advance(&ec) && !ec.value()) + { + _M_dirs->pop(); + if (_M_dirs->empty()) + { + _M_dirs.reset(); + return *this; + } + } + return *this; +} + +void +fs::recursive_directory_iterator::pop() +{ + if (!_M_dirs) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "cannot pop non-dereferenceable recursive directory iterator", + std::make_error_code(errc::invalid_argument))); + + do { + _M_dirs->pop(); + if (_M_dirs->empty()) + { + _M_dirs.reset(); + return; + } + } while (!_M_dirs->top().advance(nullptr)); +} diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc new file mode 100644 index 00000000000..091ca722fbb --- /dev/null +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -0,0 +1,1169 @@ +// Filesystem operations -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include +#include +#include +#include +#include +#include +#ifdef _GLIBCXX_HAVE_UNISTD_H +# include +# if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H) +# include +# include +# endif +#endif +#ifdef _GLIBCXX_HAVE_FCNTL_H +# include +#endif +#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H +# include +#endif +#ifdef _GLIBCXX_HAVE_GNU_SENDFILE +# include +#else +# include +# include +#endif + +namespace fs = std::experimental::filesystem; + +fs::path +fs::absolute(const path& p, const path& base) +{ + const bool has_root_dir = p.has_root_directory(); + const bool has_root_name = p.has_root_name(); + path abs; + if (has_root_dir && has_root_name) + abs = p; + else + { + abs = base.is_absolute() ? base : absolute(base); + if (has_root_dir) + abs = abs.root_name() / p; + else if (has_root_name) + abs = p.root_name() / abs.root_directory() / abs.relative_path() + / p.relative_path(); + else + abs = abs / p; + } + return abs; +} + +namespace +{ + struct free_as_in_malloc + { + void operator()(void* p) const { ::free(p); } + }; + + using char_ptr = std::unique_ptr; +} + +fs::path +fs::canonical(const path& p, const path& base, error_code& ec) +{ + path can; +#ifdef _GLIBCXX_USE_REALPATH + if (char_ptr rp = char_ptr{::realpath(absolute(p, base).c_str(), nullptr)}) + { + can.assign(rp.get()); + ec.clear(); + } + else + ec.assign(errno, std::generic_category()); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif + return can; +} + +fs::path +fs::canonical(const path& p, error_code& ec) +{ + path cur = current_path(ec); + if (ec.value()) + return {}; + return canonical(p, cur, ec); +} + +fs::path +fs::canonical(const path& p, const path& base) +{ + error_code ec; + path can = canonical(p, base, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot canonicalize", p, ec)); + return can; +} + +void +fs::copy(const path& from, const path& to, copy_options options) +{ + error_code ec; + copy(from, to, options, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy", from, to, ec)); +} + +namespace +{ + template + bool is_set(Bitmask obj, Bitmask bits) + { + return (obj & bits) != Bitmask::none; + } +} + +#ifdef _GLIBCXX_HAVE_SYS_STAT_H +namespace +{ + fs::file_status + make_file_status(const struct ::stat& st) + { + using fs::file_status; + using fs::file_type; + using fs::perms; + file_type ft; + perms perm = static_cast(st.st_mode) & perms::mask; +#ifdef _GLIBCXX_HAVE_S_ISREG + if (S_ISREG(st.st_mode)) + ft = file_type::regular; + else if (S_ISDIR(st.st_mode)) + ft = file_type::directory; + else if (S_ISCHR(st.st_mode)) + ft = file_type::character; + else if (S_ISBLK(st.st_mode)) + ft = file_type::block; + else if (S_ISFIFO(st.st_mode)) + ft = file_type::fifo; + else if (S_ISLNK(st.st_mode)) + ft = file_type::symlink; + else if (S_ISSOCK(st.st_mode)) + ft = file_type::socket; + else +#endif + ft = file_type::unknown; + return file_status{ft, perm}; + } + + inline bool + is_not_found_errno(int err) + { + return err == ENOENT || err == ENOTDIR; + } + + inline fs::file_time_type + file_time(const struct ::stat& st) + { + using namespace std::chrono; + return fs::file_time_type{ +#ifdef _GLIBCXX_USE_ST_MTIM + seconds{st.st_mtim.tv_sec} + nanoseconds{st.st_mtim.tv_nsec} +#else + seconds{st.st_mtime} +#endif + }; + } + + bool + do_copy_file(const fs::path& from, const fs::path& to, + fs::copy_options option, + struct ::stat* from_st, struct ::stat* to_st, + std::error_code& ec) noexcept + { + struct ::stat st1, st2; + fs::file_status t, f; + + if (to_st == nullptr) + { + if (::stat(to.c_str(), &st1)) + { + int err = errno; + if (!is_not_found_errno(err)) + { + ec.assign(err, std::generic_category()); + return false; + } + } + else + to_st = &st1; + } + else if (to_st == from_st) + to_st = nullptr; + + if (to_st == nullptr) + t = fs::file_status{fs::file_type::not_found}; + else + t = make_file_status(*to_st); + + if (from_st == nullptr) + { + if (::stat(from.c_str(), &st2)) + { + ec.assign(errno, std::generic_category()); + return false; + } + else + from_st = &st2; + } + f = make_file_status(*from_st); + + if (exists(t)) + { + if (!is_other(t) && !is_other(f) + && to_st->st_dev == from_st->st_dev + && to_st->st_ino == from_st->st_ino) + { + ec = std::make_error_code(std::errc::file_exists); + return false; + } + + if (is_set(option, fs::copy_options::skip_existing)) + { + ec.clear(); + return false; + } + else if (is_set(option, fs::copy_options::update_existing)) + { + if (file_time(*from_st) <= file_time(*to_st)) + { + ec.clear(); + return false; + } + } + else if (!is_set(option, fs::copy_options::overwrite_existing)) + { + ec = std::make_error_code(std::errc::file_exists); + return false; + } + } + + struct CloseFD { + ~CloseFD() { if (fd != -1) ::close(fd); } + int fd; + }; + + CloseFD in = { ::open(from.c_str(), O_RDONLY) }; + if (in.fd == -1) + { + ec.assign(errno, std::generic_category()); + return false; + } + CloseFD out = { ::open(to.c_str(), O_WRONLY|O_CREAT) }; + if (out.fd == -1) + { + ec.assign(errno, std::generic_category()); + return false; + } + +#ifdef _GLIBCXX_HAVE_GNU_SENDFILE + auto n = ::sendfile(out.fd, in.fd, nullptr, from_st->st_size); + if (n != from_st->st_size) + { + ec.assign(errno, std::generic_category()); + return false; + } +#else + __gnu_cxx::stdio_filebuf sbin(in.fd, std::ios::in); + __gnu_cxx::stdio_filebuf sbout(out.fd, std::ios::out); + if (std::ostream(&sbout) << &sbin) + { + ec.clear(); + return true; + } + else + { + ec = std::make_error_code(std::errc::io_error); + return false; + } +#endif + +#ifdef _GLIBCXX_HAVE_FCHMOD + if (::fchmod(out.fd, from_st->st_mode)) +#else + if (::chmod(to.c_str(), from_st->st_mode)) +#endif + { + ec.assign(errno, std::generic_category()); + return false; + } + return true; + } +} +#endif + +void +fs::copy(const path& from, const path& to, copy_options options, + error_code& ec) noexcept +{ + bool skip_symlinks = is_set(options, copy_options::skip_symlinks); + bool create_symlinks = is_set(options, copy_options::create_symlinks); + bool use_lstat = create_symlinks || skip_symlinks; + + file_status f, t; + struct ::stat from_st, to_st; + if (use_lstat + ? ::lstat(from.c_str(), &from_st) + : ::stat(from.c_str(), &from_st)) + { + ec.assign(errno, std::generic_category()); + return; + } + if (use_lstat + ? ::lstat(to.c_str(), &to_st) + : ::stat(to.c_str(), &to_st)) + { + if (!is_not_found_errno(errno)) + { + ec.assign(errno, std::generic_category()); + return; + } + t = file_status{file_type::not_found}; + } + else + t = make_file_status(to_st); + f = make_file_status(from_st); + + if (exists(t) && !is_other(t) && !is_other(f) + && to_st.st_dev == from_st.st_dev && to_st.st_ino == from_st.st_ino) + { + ec = std::make_error_code(std::errc::file_exists); + return; + } + if (is_other(f) || is_other(t)) + { + ec = std::make_error_code(std::errc::not_supported); + return; + } + if (is_directory(f) && is_regular_file(t)) + { + ec = std::make_error_code(std::errc::is_a_directory); + return; + } + + if (is_symlink(f)) + { + if (skip_symlinks) + ec.clear(); + else if (!exists(t) && is_set(options, copy_options::copy_symlinks)) + copy_symlink(from, to, ec); + else + // Not clear what should be done here. + // "Otherwise report an error as specified in Error reporting (7)." + ec = std::make_error_code(std::errc::invalid_argument); + } + else if (is_regular_file(f)) + { + if (is_set(options, copy_options::directories_only)) + ec.clear(); + else if (create_symlinks) + create_symlink(from, to, ec); + else if (is_set(options, copy_options::create_hard_links)) + create_hard_link(from, to, ec); + else if (is_directory(t)) + do_copy_file(from, to / from.filename(), options, &from_st, 0, ec); + else + { + auto ptr = exists(t) ? &to_st : &from_st; + do_copy_file(from, to, options, &from_st, ptr, ec); + } + } + else if (is_directory(f) && (is_set(options, copy_options::recursive) + || options == copy_options::none)) + { + if (!exists(t)) + if (!create_directory(to, from, ec)) + return; + // set an unused bit in options to disable further recursion + if (!is_set(options, copy_options::recursive)) + options |= static_cast(4096); + for (const directory_entry& x : directory_iterator(from)) + copy(x.path(), to/x.path().filename(), options, ec); + } + // "Otherwise no effects." (should ec.clear() be called?) +} + +bool +fs::copy_file(const path& from, const path& to, copy_options option) +{ + error_code ec; + bool result = copy_file(from, to, option, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy file", from, to, + ec)); + return result; +} + +bool +fs::copy_file(const path& from, const path& to, copy_options option, + error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_SYS_STAT_H + return do_copy_file(from, to, option, nullptr, nullptr, ec); +#else + ec = std::make_error_code(std::errc::not_supported); + return false; +#endif +} + + +void +fs::copy_symlink(const path& existing_symlink, const path& new_symlink) +{ + error_code ec; + copy_symlink(existing_symlink, new_symlink, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot copy symlink", + existing_symlink, new_symlink, ec)); +} + +void +fs::copy_symlink(const path& existing_symlink, const path& new_symlink, + error_code& ec) noexcept +{ + auto p = read_symlink(existing_symlink, ec); + if (ec.value()) + return; +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + if (is_directory(p)) + { + create_directory_symlink(p, new_symlink, ec); + return; + } +#endif + create_symlink(p, new_symlink, ec); +} + + +bool +fs::create_directories(const path& p) +{ + error_code ec; + bool result = create_directories(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directories", p, + ec)); + return result; +} + +bool +fs::create_directories(const path& p, error_code& ec) noexcept +{ + std::stack missing; + path pp = p; + ec.clear(); + while (!p.empty() && !exists(pp, ec) && !ec.value()) + { + missing.push(pp); + pp = pp.parent_path(); + } + while (!missing.empty() && !ec.value()) + { + create_directory(missing.top(), ec); + missing.pop(); + } + return missing.empty(); +} + +namespace +{ + bool + create_dir(const fs::path& p, fs::perms perm, std::error_code& ec) + { +#ifdef _GLIBCXX_HAVE_SYS_STAT_H + ::mode_t mode = static_cast>(perm); + if (::mkdir(p.c_str(), mode)) + { + ec.assign(errno, std::generic_category()); + return false; + } + else + { + ec.clear(); + return true; + } +#else + ec = std::make_error_code(std::errc::not_supported); + return false; +#endif + } +} // namespace + +bool +fs::create_directory(const path& p) +{ + error_code ec; + bool result = create_directory(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p, + ec)); + return result; +} + +bool +fs::create_directory(const path& p, error_code& ec) noexcept +{ + return create_dir(p, perms::all, ec); +} + + +bool +fs::create_directory(const path& p, const path& attributes) +{ + error_code ec; + bool result = create_directory(p, attributes, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory", p, + ec)); + return result; +} + +bool +fs::create_directory(const path& p, const path& attributes, + error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_SYS_STAT_H + struct ::stat st; + if (::stat(attributes.c_str(), &st)) + { + ec.assign(errno, std::generic_category()); + return false; + } + return create_dir(p, static_cast(st.st_mode), ec); +#else + ec = std::make_error_code(std::errc::not_supported); + return false; +#endif +} + + +void +fs::create_directory_symlink(const path& to, const path& new_symlink) +{ + error_code ec; + create_directory_symlink(to, new_symlink, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create directory symlink", + to, new_symlink, ec)); +} + +void +fs::create_directory_symlink(const path& to, const path& new_symlink, + error_code& ec) noexcept +{ +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + ec = std::make_error_code(std::errc::not_supported); +#else + create_symlink(to, new_symlink, ec); +#endif +} + + +void +fs::create_hard_link(const path& to, const path& new_hard_link) +{ + error_code ec; + create_hard_link(to, new_hard_link, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create hard link", + to, new_hard_link, ec)); +} + +void +fs::create_hard_link(const path& to, const path& new_hard_link, + error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_UNISTD_H + if (::link(to.c_str(), new_hard_link.c_str())) + ec.assign(errno, std::generic_category()); + else + ec.clear(); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif +} + +void +fs::create_symlink(const path& to, const path& new_symlink) +{ + error_code ec; + create_symlink(to, new_symlink, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot create symlink", + to, new_symlink, ec)); +} + +void +fs::create_symlink(const path& to, const path& new_symlink, + error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_UNISTD_H + if (::symlink(to.c_str(), new_symlink.c_str())) + ec.assign(errno, std::generic_category()); + else + ec.clear(); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif +} + + +fs::path +fs::current_path() +{ + error_code ec; + path p = current_path(ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get current path", ec)); + return p; +} + +fs::path +fs::current_path(error_code& ec) +{ + path p; +#ifdef _GLIBCXX_HAVE_UNISTD_H +#ifdef __GLIBC__ + if (char_ptr cwd = char_ptr{::getcwd(nullptr, 0)}) + { + p.assign(cwd.get()); + ec.clear(); + } + else + ec.assign(errno, std::generic_category()); +#else + long path_max = pathconf(".", _PC_PATH_MAX); + size_t size; + if (path_max == -1) + size = 1024; + else if (path_max > 10240) + size = 10240; + else + size = path_max; + for (char_ptr buf; p.empty(); size *= 2) + { + buf.reset((char*)malloc(size)); + if (buf) + { + if (getcwd(buf.get(), size)) + { + p.assign(buf.get()); + ec.clear(); + } + else if (errno != ERANGE) + { + ec.assign(errno, std::generic_category()); + return {}; + } + } + else + { + ec = std::make_error_code(std::errc::not_enough_memory); + return {}; + } + } +#endif // __GLIBC__ +#else // _GLIBCXX_HAVE_UNISTD_H + ec = std::make_error_code(std::errc::not_supported); +#endif + return p; +} + +void +fs::current_path(const path& p) +{ + error_code ec; + current_path(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set current path", ec)); +} + +void +fs::current_path(const path& p, error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_UNISTD_H + if (int err = ::chdir(p.c_str())) + ec.assign(err, std::generic_category()); + else + ec.clear(); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif +} + +bool +fs::equivalent(const path& p1, const path& p2) +{ + error_code ec; + auto result = equivalent(p1, p2, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot check file equivalence", + p1, p2, ec)); + return result; +} + +bool +fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_SYS_STAT_H + struct ::stat st1, st2; + if (::stat(p1.c_str(), &st1) == 0 && ::stat(p2.c_str(), &st2) == 0) + { + file_status s1 = make_file_status(st1); + file_status s2 = make_file_status(st2); + if (is_other(s1) && is_other(s2)) + { + ec = std::make_error_code(std::errc::not_supported); + return false; + } + ec.clear(); + return st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino; + } + else if (is_not_found_errno(errno)) + { + ec = std::make_error_code(std::errc::no_such_file_or_directory); + return false; + } + ec.assign(errno, std::generic_category()); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif + return false; +} + +std::uintmax_t +fs::file_size(const path& p) +{ + error_code ec; + auto sz = file_size(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file size", p, ec)); + return sz; +} + +namespace +{ + template + T + do_stat(const fs::path& p, std::error_code& ec, Accessor f, T deflt) + { +#ifdef _GLIBCXX_HAVE_SYS_STAT_H + struct ::stat st; + if (::stat(p.c_str(), &st)) + { + ec.assign(errno, std::generic_category()); + return deflt; + } + ec.clear(); + return f(st); +#else + ec = std::make_error_code(std::errc::not_supported); + return deflt; +#endif + } +} + +std::uintmax_t +fs::file_size(const path& p, error_code& ec) noexcept +{ + return do_stat(p, ec, std::mem_fn(&stat::st_size), + static_cast(-1)); +} + +std::uintmax_t +fs::hard_link_count(const path& p) +{ + error_code ec; + auto count = hard_link_count(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get link count", p, ec)); + return count; +} + +std::uintmax_t +fs::hard_link_count(const path& p, error_code& ec) noexcept +{ + return do_stat(p, ec, std::mem_fn(&stat::st_nlink), + static_cast(-1)); +} + +bool +fs::is_empty(const path& p) +{ + return fs::is_directory(status(p)) + ? fs::directory_iterator(p) == fs::directory_iterator() + : fs::file_size(p) == 0; +} + +bool +fs::is_empty(const path& p, error_code& ec) noexcept +{ + auto s = status(p, ec); + if (ec.value()) + return false; + return fs::is_directory(s) + ? fs::directory_iterator(p, ec) == fs::directory_iterator() + : fs::file_size(p, ec) == 0; +} + +fs::file_time_type +fs::last_write_time(const path& p) +{ + error_code ec; + auto t = last_write_time(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get file time", p, ec)); + return t; +} + +fs::file_time_type +fs::last_write_time(const path& p, error_code& ec) noexcept +{ + return do_stat(p, ec, [](const auto& st) { return file_time(st); }, + file_time_type::min()); +} + +void +fs::last_write_time(const path& p, file_time_type new_time) +{ + error_code ec; + last_write_time(p, new_time, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set file time", p, ec)); +} + +void +fs::last_write_time(const path& p __attribute__((__unused__)), + file_time_type new_time, error_code& ec) noexcept +{ + auto d = new_time.time_since_epoch(); + auto s = chrono::duration_cast(d); + auto ns = chrono::duration_cast(d - s); +#ifdef _GLIBCXX_USE_UTIMENSAT + struct ::timespec ts[2] = { + { 0, UTIME_OMIT }, + { static_cast(s.count()), static_cast(ns.count()) } + }; + if (utimensat(AT_FDCWD, p.c_str(), ts, 0)) + ec.assign(errno, std::generic_category()); + else + ec.clear(); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif +} + +void +fs::permissions(const path& p, perms prms) +{ + error_code ec; + permissions(p, prms, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot set permissions", p, ec)); +} + +void fs::permissions(const path& p, perms prms, error_code& ec) noexcept +{ + if (int err = ::fchmodat(AT_FDCWD, p.c_str(), static_cast(prms), 0)) + ec.assign(err, std::generic_category()); + else + ec.clear(); +} + +fs::path +fs::read_symlink(const path& p) +{ + error_code ec; + path tgt = read_symlink(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("read_symlink", p, ec)); + return tgt; +} + +fs::path fs::read_symlink(const path& p, error_code& ec) +{ +#ifdef _GLIBCXX_HAVE_SYS_STAT_H + struct ::stat st; + if (::lstat(p.c_str(), &st)) + { + ec.assign(errno, std::generic_category()); + return {}; + } + std::string buf(st.st_size, '\0'); + ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size()); + if (len == -1) + { + ec.assign(errno, std::generic_category()); + return {}; + } + return path{buf.data(), buf.data()+len}; +#else + ec = std::make_error_code(std::errc::not_supported); + return {}; +#endif +} + + +bool +fs::remove(const path& p) +{ + error_code ec; + bool result = fs::remove(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove", p, ec)); + return result; +} + +bool +fs::remove(const path& p, error_code& ec) noexcept +{ + if (exists(symlink_status(p, ec))) + { + if (::remove(p.c_str()) == 0) + { + ec.clear(); + return true; + } + else + ec.assign(errno, std::generic_category()); + } + return false; +} + + +std::uintmax_t +fs::remove_all(const path& p) +{ + error_code ec; + bool result = remove_all(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec)); + return result; +} + +std::uintmax_t +fs::remove_all(const path& p, error_code& ec) noexcept +{ + auto fs = symlink_status(p, ec); + uintmax_t count = 0; + if (ec.value() == 0 && fs.type() == file_type::directory) + for (directory_iterator d(p, ec), end; ec.value() == 0 && d != end; ++d) + count += fs::remove(d->path(), ec); + if (ec.value()) + return -1; + return fs::remove(p, ec) ? ++count : -1; // fs:remove() calls ec.clear() +} + +void +fs::rename(const path& from, const path& to) +{ + error_code ec; + rename(from, to, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot rename", from, to, ec)); +} + +void +fs::rename(const path& from, const path& to, error_code& ec) noexcept +{ + if (::rename(from.c_str(), to.c_str())) + ec.assign(errno, std::generic_category()); + else + ec.clear(); +} + +void +fs::resize_file(const path& p, uintmax_t size) +{ + error_code ec; + resize_file(p, size, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot resize file", p, ec)); +} + +void +fs::resize_file(const path& p, uintmax_t size, error_code& ec) noexcept +{ +#ifdef _GLIBCXX_HAVE_UNISTD_H + if (size > static_cast(std::numeric_limits::max())) + ec.assign(EINVAL, std::generic_category()); + else if (::truncate(p.c_str(), size)) + ec.assign(errno, std::generic_category()); + else + ec.clear(); +#else + ec = std::make_error_code(std::errc::not_supported); +#endif +} + + +fs::space_info +fs::space(const path& p) +{ + error_code ec; + space_info s = space(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot get free space", p, ec)); + return s; +} + +fs::space_info +fs::space(const path& p, error_code& ec) noexcept +{ + space_info info = { + static_cast(-1), + static_cast(-1), + static_cast(-1) + }; +#ifdef _GLIBCXX_HAVE_SYS_STATVFS_H + struct ::statvfs f; + if (int err = ::statvfs(p.c_str(), &f)) + ec.assign(err, std::generic_category()); + else + { + info = space_info{ + f.f_blocks * f.f_frsize, + f.f_bfree * f.f_frsize, + f.f_bavail * f.f_frsize + }; + ec.clear(); + } +#endif + return info; +} + +#ifdef _GLIBCXX_HAVE_SYS_STAT_H +fs::file_status +fs::status(const fs::path& p, std::error_code& ec) noexcept +{ + file_status status; + struct ::stat st; + if (::stat(p.c_str(), &st)) + { + int err = errno; + ec.assign(err, std::generic_category()); + if (is_not_found_errno(err)) + status = file_status{file_type::not_found}; + } + else + { + status = make_file_status(st); + ec.clear(); + } + return status; +} + +fs::file_status +fs::symlink_status(const fs::path& p, std::error_code& ec) noexcept +{ + file_status status; + struct ::stat st; + if (::lstat(p.c_str(), &st)) + { + int err = errno; + ec.assign(err, std::generic_category()); + if (is_not_found_errno(err)) + status = file_status{file_type::not_found}; + } + else + { + status = make_file_status(st); + ec.clear(); + } + return status; +} +#endif + +fs::file_status +fs::status(const fs::path& p) +{ + std::error_code ec; + auto s = status(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("status", p, ec)); + return s; +} + +fs::file_status +fs::symlink_status(const fs::path& p) +{ + std::error_code ec; + auto s = symlink_status(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("symlink_status", ec)); + return s; +} + +fs::path +fs::system_complete(const path& p) +{ + error_code ec; + path comp = system_complete(p, ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("system_complete", p, ec)); + return comp; +} + +fs::path +fs::system_complete(const path& p, error_code& ec) +{ + path base = current_path(ec); +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + if (p.is_absolute() || !p.has_root_name() + || p.root_name() == base.root_name()) + return absolute(p, base); + // else TODO + ec = std::make_error_code(std::errc::not_supported); + return {}; +#else + if (ec.value()) + return {}; + return absolute(p, base); +#endif +} + +fs::path fs::temp_directory_path() +{ + error_code ec; + path tmp = temp_directory_path(ec); + if (ec.value()) + _GLIBCXX_THROW_OR_ABORT(filesystem_error("temp_directory_path", ec)); + return tmp; +} + +fs::path fs::temp_directory_path(error_code& ec) +{ +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return {}; // TODO +#else + const char* tmpdir = ::getenv("TMPDIR"); + if (!tmpdir) + tmpdir = "/tmp"; + ec.clear(); + return tmpdir; +#endif +} + diff --git a/libstdc++-v3/src/filesystem/path.cc b/libstdc++-v3/src/filesystem/path.cc new file mode 100644 index 00000000000..db58f3bdb70 --- /dev/null +++ b/libstdc++-v3/src/filesystem/path.cc @@ -0,0 +1,464 @@ +// Class filesystem::path -*- C++ -*- + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#include + +using std::experimental::filesystem::path; + +constexpr path::value_type path::preferred_separator; + +path& +path::remove_filename() +{ + if (_M_type == _Type::_Multi) + { + if (!_M_cmpts.empty()) + { + auto cmpt = --_M_cmpts.end(); + _M_pathname.erase(cmpt->_M_pos); + _M_cmpts.erase(cmpt); + _M_trim(); + } + } + else + clear(); + return *this; +} + +path& +path::replace_filename(const path& replacement) +{ + remove_filename(); + operator/=(replacement); + return *this; +} + +path& +path::replace_extension(const path& replacement) +{ + auto ext = _M_find_extension(); + if (ext.first && ext.second != string_type::npos) + { + if (ext.first == &_M_pathname) + _M_pathname.erase(ext.second); + else + { + const auto& back = _M_cmpts.back(); + if (ext.first != &back._M_pathname) + _GLIBCXX_THROW_OR_ABORT( + std::logic_error("path::replace_extension failed")); + _M_pathname.erase(back._M_pos + ext.second); + } + } + if (!replacement.empty() && replacement.native()[0] != '.') + _M_pathname += '.'; + _M_pathname += replacement.native(); + _M_split_cmpts(); + return *this; +} + +namespace +{ + template + int do_compare(Iter1 begin1, Iter1 end1, Iter2 begin2, Iter2 end2) + { + int cmpt = 1; + while (begin1 != end1 && begin2 != end2) + { + if (begin1->native() < begin2->native()) + return -cmpt; + if (begin1->native() > begin2->native()) + return +cmpt; + ++begin1; + ++begin2; + ++cmpt; + } + if (begin1 == end1) + { + if (begin2 == end2) + return 0; + return -cmpt; + } + return +cmpt; + } +} + +int +path::compare(const path& p) const noexcept +{ + if (_M_type == _Type::_Multi && p._M_type == _Type::_Multi) + return do_compare(_M_cmpts.begin(), _M_cmpts.end(), + p._M_cmpts.begin(), p._M_cmpts.end()); + else if (_M_type == _Type::_Multi) + { + _Cmpt c[1] = { { p._M_pathname, p._M_type, 0 } }; + return do_compare(_M_cmpts.begin(), _M_cmpts.end(), c, c+1); + } + else if (p._M_type == _Type::_Multi) + { + _Cmpt c[1] = { { _M_pathname, _M_type, 0 } }; + return do_compare(c, c+1, p._M_cmpts.begin(), p._M_cmpts.end()); + } + else + return _M_pathname.compare(p._M_pathname); +} + +path +path::root_name() const +{ + path __ret; + if (_M_type == _Type::_Root_name) + __ret = *this; + else if (_M_cmpts.size() + && _M_cmpts.begin()->_M_type == _Type::_Root_name) + __ret = *_M_cmpts.begin(); + return __ret; +} + +path +path::root_directory() const +{ + path __ret; + if (_M_type == _Type::_Root_dir) + __ret = *this; + else if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir) + __ret = *__it; + } + return __ret; +} + + +path +path::root_path() const +{ + path __ret; + if (_M_type == _Type::_Root_name || _M_type == _Type::_Root_dir) + __ret = *this; + else if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type == _Type::_Root_name) + { + __ret = *__it++; + if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir) + { + __ret._M_pathname += preferred_separator; + __ret._M_split_cmpts(); + } + } + else if (__it->_M_type == _Type::_Root_dir) + __ret = *__it; + } + return __ret; +} + +path +path::relative_path() const +{ + path __ret; + if (_M_type == _Type::_Filename) + __ret = *this; + else if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir) + ++__it; + if (__it != _M_cmpts.end()) + __ret.assign(_M_pathname.substr(__it->_M_pos)); + } + return __ret; +} + +path +path::parent_path() const +{ + path __ret; + if (_M_cmpts.size() < 2) + return __ret; + for (auto __it = _M_cmpts.begin(), __end = --_M_cmpts.end(); + __it != __end; ++__it) + { + __ret /= *__it; + } + return __ret; +} + +bool +path::has_root_name() const +{ + if (_M_type == _Type::_Root_name) + return true; + if (!_M_cmpts.empty() && _M_cmpts.begin()->_M_type == _Type::_Root_name) + return true; + return false; +} + +bool +path::has_root_directory() const +{ + if (_M_type == _Type::_Root_dir) + return true; + if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir) + return true; + } + return false; +} + +bool +path::has_root_path() const +{ + if (_M_type == _Type::_Root_name || _M_type == _Type::_Root_dir) + return true; + if (!_M_cmpts.empty()) + { + auto __type = _M_cmpts.front()._M_type; + if (__type == _Type::_Root_name || __type == _Type::_Root_dir) + return true; + } + return false; +} + +bool +path::has_relative_path() const +{ + if (_M_type == _Type::_Filename) + return true; + if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type == _Type::_Root_dir) + ++__it; + if (__it != _M_cmpts.end()) + return true; + } + return false; +} + + +bool +path::has_parent_path() const +{ + return _M_cmpts.size() > 1; +} + +bool +path::has_filename() const +{ + return !empty(); +} + +std::pair +path::_M_find_extension() const +{ + const std::string* s = nullptr; + + if (_M_type != _Type::_Multi) + s = &_M_pathname; + else if (!_M_cmpts.empty()) + { + const auto& c = _M_cmpts.back(); + if (c._M_type == _Type::_Filename) + s = &c._M_pathname; + } + + if (s) + { + if (auto sz = s->size()) + { + if (sz <= 2 && (*s)[0] == '.') + { + if (sz == 1 || (*s)[1] == '.') // filename is "." or ".." + return { s, string_type::npos }; + else + return { s, 0 }; // filename is like ".?" + } + return { s, s->rfind('.') }; + } + } + return {}; +} + +void +path::_M_split_cmpts() +{ + _M_type = _Type::_Multi; + _M_cmpts.clear(); + + if (_M_pathname.empty()) + return; + + size_t pos = 0; + const size_t len = _M_pathname.size(); + + // look for root name or root directory + if (_S_is_dir_sep(_M_pathname[0])) + { + // look for root name, such as "//" or "//foo" + if (len > 1 && _M_pathname[1] == _M_pathname[0]) + { + if (len == 2) + { + // entire path is just "//" + _M_type = _Type::_Root_name; + return; + } + + if (!_S_is_dir_sep(_M_pathname[2])) + { + // got root name, find its end + pos = 3; + while (pos < len && !_S_is_dir_sep(_M_pathname[pos])) + ++pos; + _M_add_root_name(pos); + if (pos < len) // also got root directory + _M_add_root_dir(pos); + } + else + { + // got something like "///foo" which is just a root directory + // composed of multiple redundant directory separators + _M_add_root_dir(0); + } + } + else // got root directory + _M_add_root_dir(0); + ++pos; + } +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + else if (len > 1 && _M_pathname[1] == L':') + { + // got disk designator + _M_add_root_name(2); + if (len > 2 && _S_is_dir_sep(_M_pathname[2])) + _M_add_root_dir(2); + pos = 2; + } +#endif + + size_t back = pos; + while (pos < len) + { + if (_S_is_dir_sep(_M_pathname[pos])) + { + if (back != pos) + _M_add_filename(back, pos - back); + back = ++pos; + } + else + ++pos; + } + + if (back != pos) + _M_add_filename(back, pos - back); + else if (_S_is_dir_sep(_M_pathname.back())) + { + // [path.itr]/8 + // "Dot, if one or more trailing non-root slash characters are present." + if (_M_cmpts.back()._M_type == _Type::_Filename) + { + const auto& last = _M_cmpts.back(); + pos = last._M_pos + last._M_pathname.size(); + _M_cmpts.emplace_back(string_type(1, '.'), _Type::_Filename, pos); + } + } + + _M_trim(); +} + +void +path::_M_add_root_name(size_t n) +{ + _M_cmpts.emplace_back(_M_pathname.substr(0, n), _Type::_Root_name, 0); +} + +void +path::_M_add_root_dir(size_t pos) +{ + _M_cmpts.emplace_back(_M_pathname.substr(pos, 1), _Type::_Root_dir, pos); +} + +void +path::_M_add_filename(size_t pos, size_t n) +{ + _M_cmpts.emplace_back(_M_pathname.substr(pos, n), _Type::_Filename, pos); +} + +void +path::_M_trim() +{ + if (_M_cmpts.size() == 1) + { + _M_type = _M_cmpts.front()._M_type; + _M_cmpts.clear(); + } +} + +path::string_type +path::_S_convert_loc(const char* __first, const char* __last, + const std::locale& __loc) +{ + auto& __cvt = std::use_facet>(__loc); + basic_string __ws; + if (!__str_codecvt_in(__first, __last, __ws, __cvt)) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return __ws; +#else + return _Cvt::_S_convert(__ws.data(), __ws.data() + __ws.size()); +#endif +} + +std::size_t +std::experimental::filesystem::hash_value(const path& p) noexcept +{ + // [path.non-member] + // "If for two paths, p1 == p2 then hash_value(p1) == hash_value(p2)." + // Equality works as if by traversing the range [begin(), end()), meaning + // e.g. path("a//b") == path("a/b"), so we cannot simply hash _M_pathname + // but need to iterate over individual elements. Use the hash_combine from + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3876.pdf + size_t seed = 0; + for (const auto& x : p) + { + seed ^= std::hash()(x.native()) + 0x9e3779b9 + + (seed<<6) + (seed>>2); + } + return seed; +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc new file mode 100644 index 00000000000..14625b5bc2c --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc @@ -0,0 +1,55 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 15.1 Absolute [fs.op.absolute] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + VERIFY( absolute(p).is_absolute() ); +} + +void +test02() +{ + path p1("/"); + VERIFY( absolute(p1) == p1 ); + VERIFY( absolute(p1, "/bar") == p1 ); + path p2("/foo"); + VERIFY( absolute(p2) == p2 ); + VERIFY( absolute(p2, "/bar") == p2 ); + path p3("foo"); + VERIFY( absolute(p3) != p3 ); + VERIFY( absolute(p3, "/bar") == "/bar/foo" ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc new file mode 100644 index 00000000000..2410c802f23 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc @@ -0,0 +1,55 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 15.3 Copy [fs.op.copy] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + VERIFY( absolute(p).is_absolute() ); +} + +void +test02() +{ + path p1("/"); + VERIFY( absolute(p1) == p1 ); + VERIFY( absolute(p1, "/bar") == p1 ); + path p2("/foo"); + VERIFY( absolute(p2) == p2 ); + VERIFY( absolute(p2, "/bar") == p2 ); + path p3("foo"); + VERIFY( absolute(p3) != p3 ); + VERIFY( absolute(p3, "/bar") == "/bar/foo" ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc new file mode 100644 index 00000000000..325a5a852fd --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc @@ -0,0 +1,57 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 15.11 Current path [fs.op.current_path] + +#include +#include +#include + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + fs::path dot("."); + fs::path cwd = fs::current_path(); + std::error_code ec; + fs::path cwd2 = fs::current_path(ec); + VERIFY( cwd == cwd2 ); +} + +void +test02() +{ + auto oldwd = fs::current_path(); + auto tmpdir = fs::temp_directory_path(); + current_path(tmpdir); + VERIFY( fs::current_path() == tmpdir ); + std::error_code ec; + current_path(oldwd, ec); + VERIFY( fs::current_path() == oldwd ); + VERIFY( fs::current_path(ec) == oldwd ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/append/path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/append/path.cc new file mode 100644 index 00000000000..75d2df0c8a3 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/append/path.cc @@ -0,0 +1,63 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.3 path appends [path.append] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + const path p("/foo/bar"); + + path pp = p; + pp /= p; + VERIFY( pp.native() == "/foo/bar/foo/bar" ); + + path q("baz"); + + path qq = q; + qq /= q; + VERIFY( qq.native() == "baz/baz" ); + + q /= p; + VERIFY( q.native() == "baz/foo/bar" ); + + path r = ""; + r /= path(); + VERIFY( r.empty() ); + + r /= path("rel"); + VERIFY( !r.is_absolute() ); + + path s = "dir/"; + s /= path("/file"); + VERIFY( s.native() == "dir//file" ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc new file mode 100644 index 00000000000..6fd24a77cf3 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc @@ -0,0 +1,89 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +using std::experimental::filesystem::path; +using __gnu_test::compare_paths; + +void +test01() +{ + for (std::string s : __gnu_test::test_paths) + { + path p0 = s, p1, p2, p3, p4; + + p1 = s; + compare_paths(p0, p1); + + p2 = s.c_str(); + compare_paths(p0, p2); + + std::wstring ws(s.begin(), s.end()); + + p3 = ws; + compare_paths(p0, p3); + + p4 = ws.c_str(); + compare_paths(p0, p4); + } +} + +void +test02() +{ + for (std::string s : __gnu_test::test_paths) + { + path p0 = s, p1, p2, p3, p4, p5, p6, p7, p8; + + p1.assign(s); + compare_paths(p0, p1); + + p2.assign( s.begin(), s.end() ); + compare_paths(p0, p2); + + p3.assign( s.c_str() ); + compare_paths(p0, p3); + + p4.assign( s.c_str(), s.c_str() + s.size() ); + compare_paths(p0, p4); + + std::wstring ws(s.begin(), s.end()); + + p5.assign(ws); + compare_paths(p0, p5); + + p6.assign( ws.begin(), ws.end() ); + compare_paths(p0, p6); + + p7.assign( ws.c_str() ); + compare_paths(p0, p7); + + p8.assign( ws.c_str(), ws.c_str() + ws.size() ); + compare_paths(p0, p8); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/assign/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/assign/copy.cc new file mode 100644 index 00000000000..29dbcd4035d --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/assign/copy.cc @@ -0,0 +1,55 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::experimental::filesystem::path; +using __gnu_test::compare_paths; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + path copy; + copy = p; + __gnu_test::compare_paths(p, copy); + } +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path copy = p; + path move; + move = std::move(copy); + __gnu_test::compare_paths(p, move); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/compare/compare.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/compare/compare.cc new file mode 100644 index 00000000000..e8f5e41cfa1 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/compare/compare.cc @@ -0,0 +1,50 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.8 path compare [path.compare] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p("/foo/bar"); + VERIFY( p.compare(p) == 0 ); + VERIFY( p.compare("/foo//bar") == 0 ); + + path q("/foo/baz"); + VERIFY( p.compare(q) < 0 ); + VERIFY( q.compare(p) > 0 ); + + path r("/foo/bar/."); + VERIFY( p.compare(r) < 0 ); + + VERIFY( path("a/b/").compare("a/b/.") == 0 ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/compare/path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/compare/path.cc new file mode 100644 index 00000000000..7858af16228 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/compare/path.cc @@ -0,0 +1,50 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.8 path compare [path.compare] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + const path p0 = "/a/a/b/b"; + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.compare(p) == 0 ); + int cmp = p.compare(p0); + if (cmp == 0) + VERIFY( p0.compare(p) == 0 ); + else if (cmp < 0) + VERIFY( p0.compare(p) > 0 ); + else if (cmp > 0) + VERIFY( p0.compare(p) < 0 ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/compare/strings.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/compare/strings.cc new file mode 100644 index 00000000000..7e6156819ad --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/compare/strings.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.8 path compare [path.compare] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + const std::string s0 = "/a/a/b/b"; + const path p0 = s0; + for (const std::string& s : __gnu_test::test_paths) + { + path p(s); + VERIFY( p.compare(s) == 0 ); + VERIFY( p.compare(s.c_str()) == 0 ); + VERIFY( p.compare(p0) == p.compare(s0) ); + VERIFY( p.compare(p0) == p.compare(s0.c_str()) ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/concat/path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/path.cc new file mode 100644 index 00000000000..fceae117d2e --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/path.cc @@ -0,0 +1,68 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.4 path concatenation [path.concat] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + const path p("/foo/bar"); + + path pp = p; + pp += p; + VERIFY( pp.native() == "/foo/bar/foo/bar" ); + VERIFY( std::distance(pp.begin(), pp.end()) == 5 ); + + path q("foo/bar"); + + path qq = q; + qq += q; + VERIFY( qq.native() == "foo/barfoo/bar" ); + VERIFY( std::distance(qq.begin(), qq.end()) == 3 ); + + q += p; + VERIFY( q.native() == "foo/bar/foo/bar" ); + VERIFY( std::distance(q.begin(), q.end()) == 4 ); +} + +void +test02() +{ + for (path p : __gnu_test::test_paths) + { + auto prior_native = p.native(); + path x("//blah/di/blah"); + p += x; + VERIFY( p.native() == prior_native + x.native() ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc new file mode 100644 index 00000000000..e75e790a491 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.4 path concatenation [path.concat] + +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p("/"); + p += path::string_type("foo"); + VERIFY( p.filename() == "foo" ); + p += "bar"; + VERIFY( p.filename() == "foobar" ); + p += '/'; + VERIFY( p.parent_path() == "/foobar" && p.filename() == "." ); + p += L"baz.txt"; + VERIFY( p.filename() == "baz.txt" ); + p.concat("/dir/"); + VERIFY( p.parent_path() == "/foobar/baz.txt/dir" && p.filename() == "." ); + std::string file = "file"; + p.concat(file.begin(), file.end()); + VERIFY( p.filename() == "file" ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/copy.cc new file mode 100644 index 00000000000..d0180b6c0a2 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/copy.cc @@ -0,0 +1,54 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.1 path constructors [path.construct] + +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + path copy = p; + __gnu_test::compare_paths(p, copy); + } +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path copy = p; + path move = std::move(copy); + __gnu_test::compare_paths(p, move); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/default.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/default.cc new file mode 100644 index 00000000000..d8952a73726 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/default.cc @@ -0,0 +1,50 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.1 path constructors [path.construct] + +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p; + VERIFY( p.empty() ); + VERIFY( !p.has_root_path() ); + VERIFY( !p.has_root_name() ); + VERIFY( !p.has_root_directory() ); + VERIFY( !p.has_relative_path() ); + VERIFY( !p.has_parent_path() ); + VERIFY( !p.has_filename() ); + VERIFY( !p.has_stem() ); + VERIFY( !p.has_extension() ); + VERIFY( !p.is_absolute() ); + VERIFY( p.is_relative() ); + VERIFY( std::distance(p.begin(), p.end()) == 0 ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/locale.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/locale.cc new file mode 100644 index 00000000000..4c8c1841599 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/locale.cc @@ -0,0 +1,39 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.1 path constructors [path.construct] + +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p("/foo/bar", std::locale::classic()); + VERIFY( p.string() == "/foo/bar" ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc new file mode 100644 index 00000000000..03e50854772 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.1 path constructors [path.construct] + +#include +#include +#include + +using std::experimental::filesystem::path; +using __gnu_test::compare_paths; + +void +test01() +{ + for (std::string s : __gnu_test::test_paths) + { + path p1 = s; + path p2( s.begin(), s.end() ); + path p3( s.c_str() ); + path p4( s.c_str(), s.c_str() + s.size() ); + + std::wstring ws(s.begin(), s.end()); + path p5 = ws; + path p6( ws.begin(), ws.end() ); + path p7( ws.c_str() ); + path p8( ws.c_str(), ws.c_str() + ws.size() ); + + compare_paths(p1, p2); + compare_paths(p1, p3); + compare_paths(p1, p4); + compare_paths(p1, p5); + compare_paths(p1, p6); + compare_paths(p1, p7); + compare_paths(p1, p8); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/extension.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/extension.cc new file mode 100644 index 00000000000..96f5bf5344e --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/extension.cc @@ -0,0 +1,61 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo/bar.txt").extension() == path(".txt") ); + VERIFY( path("/foo/bar.baz.txt").extension() == path(".txt") ); + VERIFY( path(".bar.baz.txt").extension() == path(".txt") ); + + VERIFY( path(".hidden").extension() == path(".hidden") ); + + VERIFY( path().extension() == path() ); + VERIFY( path(".").extension() == path() ); + VERIFY( path("..").extension() == path() ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + auto stem = p.stem(); + auto ext = p.extension(); + auto file = p.filename(); + VERIFY( stem.native() + ext.native() == file.native() ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/filename.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/filename.cc new file mode 100644 index 00000000000..dc3f07ff693 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/filename.cc @@ -0,0 +1,58 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo/bar.txt").filename() == "bar.txt" ); + VERIFY( path("/").filename() == "/" ); + VERIFY( path(".").filename() == "." ); + VERIFY( path("..").filename() == ".." ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path f = p.filename(); + if (p.empty()) + VERIFY( f.empty() ); + else + VERIFY( f == *--p.end() ); + if (p != p.root_path()) + VERIFY( !f.has_root_path() ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/parent_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/parent_path.cc new file mode 100644 index 00000000000..2c21f6ff699 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/parent_path.cc @@ -0,0 +1,61 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p0; + VERIFY( p0.parent_path() == p0 ); + path p1 = "foo"; + VERIFY( p1.parent_path() == p0 ); + path p2 = "foo/bar"; + VERIFY( p2.parent_path() == p1 ); + path p3 = "/foo/bar"; + VERIFY( p3.parent_path() == path("/foo") ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path pp; + for (auto i = p.begin(), end = --p.end(); i != end; ++i) + { + pp /= *i; + } + VERIFY( p.parent_path() == pp ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/relative_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/relative_path.cc new file mode 100644 index 00000000000..16e8f864ad8 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/relative_path.cc @@ -0,0 +1,65 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p1 = "foo"; + VERIFY( p1.relative_path() == p1 ); + path p2 = "foo/bar"; + VERIFY( p2.relative_path() == p2 ); + path p3 = "/foo/bar"; + VERIFY( p3.relative_path() == p2 ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + bool after_root = false; + const path prel = p.relative_path(); + VERIFY( !prel.has_root_name() ); + path rel; + for (const auto& cmpt : p) + { + if (!cmpt.has_root_path()) + after_root = true; + if (after_root) + rel /= cmpt; + } + VERIFY( prel == rel ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_directory.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_directory.cc new file mode 100644 index 00000000000..4f372d6ddb3 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_directory.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p1 = "foo/bar"; + VERIFY( p1.root_directory() == path() ); + path p2 = "/foo/bar"; + VERIFY( p2.root_directory() == path("/") ); + path p3 = "//foo"; + VERIFY( p3.root_directory() == path() ); + path p4 = "///foo"; + VERIFY( p4.root_directory() == path("/") ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path rootdir = p.root_directory(); + // If root-directory is composed of 'slash name', + // 'slash' is excluded from the returned string. + if (!rootdir.empty() && rootdir.native() != "/") + VERIFY( rootdir.native()[0] != '/' ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_name.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_name.cc new file mode 100644 index 00000000000..01886738be4 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_name.cc @@ -0,0 +1,42 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo/bar.txt").extension() == ".txt" ); + VERIFY( path("/foo/bar.baz.txt").extension() == ".txt" ); + VERIFY( path(".").extension().empty() ); + VERIFY( path("..").extension().empty() ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_path.cc new file mode 100644 index 00000000000..feb4e7995dd --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/root_path.cc @@ -0,0 +1,55 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p1 = "foo/bar"; + VERIFY( p1.root_path() == path() ); + path p2 = "/foo/bar"; + VERIFY( p2.root_path() == path("/") ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path rootp = p.root_path(); + path rootn = p.root_name(); + path rootd = p.root_directory(); + VERIFY( rootp == (rootn / rootd) ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/stem.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/stem.cc new file mode 100644 index 00000000000..d3611b88776 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/decompose/stem.cc @@ -0,0 +1,53 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo/bar.txt").stem() == path("bar") ); + path p = "foo.bar.baz.tar"; + std::vector v; + for (; !p.extension().empty(); p = p.stem()) + v.push_back(p.extension().native()); + VERIFY( v.at(0) == ".tar" ); + VERIFY( v.at(1) == ".baz" ); + VERIFY( v.at(2) == ".bar" ); + + VERIFY( path(".hidden").stem() == path() ); + + VERIFY( path().stem() == path() ); + VERIFY( path(".").stem() == path(".") ); + VERIFY( path("..").stem() == path("..") ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc new file mode 100644 index 00000000000..1e302f2bf72 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/generic/generic_string.cc @@ -0,0 +1,48 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.7 path generic format observers [path.generic.obs] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + path p2(p), p3; + p2.swap(p3); + VERIFY( p2 == path() ); + VERIFY( p3 == p ); + p2.swap(p3); + VERIFY( p2 == p ); + VERIFY( p3 == path() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/itr/traversal.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/itr/traversal.cc new file mode 100644 index 00000000000..0e543349d98 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/itr/traversal.cc @@ -0,0 +1,86 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.5 path iterators [path.itr] + +#include +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + path p; + VERIFY( p.begin() == p.end() ); + + std::vector v, v2; + + p = "/"; + v.assign(p.begin(), p.end()); + v2 = { "/" }; + VERIFY( v == v2 ); + + p = "filename"; + v.assign(p.begin(), p.end()); + v2 = { "filename" }; + VERIFY( v == v2 ); + + p = "dir/"; + v.assign(p.begin(), p.end()); + v2 = { "dir", "." }; + VERIFY( v == v2 ); + + p = "//rootname/dir/"; + v.assign(p.begin(), p.end()); + v2 = { "//rootname", "/", "dir", "." }; + VERIFY( v == v2 ); + + p = "//rootname/dir/filename"; + v.assign(p.begin(), p.end()); + v2 = { "//rootname", "/", "dir", "filename" }; + VERIFY( v == v2 ); +} + +void +test02() +{ + using reverse_iterator = std::reverse_iterator; + std::vector fwd, rev; + + for (const path& p : __gnu_test::test_paths) + { + const auto begin = p.begin(), end = p.end(); + fwd.assign(begin, end); + rev.assign(reverse_iterator(end), reverse_iterator(begin)); + VERIFY( fwd.size() == rev.size() ); + VERIFY( std::equal(fwd.begin(), fwd.end(), rev.rbegin()) ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/clear.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/clear.cc new file mode 100644 index 00000000000..e28f900315a --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/clear.cc @@ -0,0 +1,45 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.5 path modifiers [path.modifiers] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (path p : __gnu_test::test_paths) + { + path empty; + p.clear(); + VERIFY( p.empty() ); + __gnu_test::compare_paths(p, empty); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/make_preferred.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/make_preferred.cc new file mode 100644 index 00000000000..f38ecf6fc05 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/make_preferred.cc @@ -0,0 +1,63 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.5 path modifiers [path.modifiers] + +#include +#include +#include + +using std::experimental::filesystem::path; + +template +struct checker +{ + static void check(const char* s) { } +}; + +template<> +struct checker +{ + static void check() + { + VERIFY( path("foo/bar").make_preferred() == "foo/bar" ); + } +}; + +template<> +struct checker +{ + static void check() + { + VERIFY( path("foo/bar").make_preferred() == L"foo\\bar" ); + } +}; + +void +test01() +{ + checker::check(); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/remove_filename.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/remove_filename.cc new file mode 100644 index 00000000000..4612e4490d6 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/remove_filename.cc @@ -0,0 +1,53 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.5 path modifiers [path.modifiers] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo").remove_filename() == "/" ); + VERIFY( path("/").remove_filename() == "" ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path p2(p); + p2.remove_filename(); + p2 /= p.filename(); + VERIFY( p2 == p ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_extension.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_extension.cc new file mode 100644 index 00000000000..163016b09a1 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_extension.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.5 path modifiers [path.modifiers] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo.txt").replace_extension("cpp") == "/foo.cpp" ); + VERIFY( path("/foo.txt").replace_extension(".cpp") == "/foo.cpp" ); + VERIFY( path("/").replace_extension("bar") == "/.bar" ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path p2 = p; + VERIFY(p2.replace_extension(p2.extension()) == p); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_filename.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_filename.cc new file mode 100644 index 00000000000..c9706008a07 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/replace_filename.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.5 path modifiers [path.modifiers] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( path("/foo").replace_filename("bar") == "/bar" ); + VERIFY( path("/").replace_filename("bar") == "bar" ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path p2(p); + p2.replace_filename(p.filename()); + VERIFY( p2 == p ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/swap.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/swap.cc new file mode 100644 index 00000000000..df990e05f41 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/modifiers/swap.cc @@ -0,0 +1,44 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.5 path modifiers [path.modifiers] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + const path p("/foo/bar"); + path p1; + path p2 = p; + p1.swap(p2); + VERIFY( p2.empty() ); + __gnu_test::compare_paths(p1, p); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/nonmember/hash_value.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/nonmember/hash_value.cc new file mode 100644 index 00000000000..3971237a657 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/nonmember/hash_value.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.6 path non-member functions [path.non-member] + +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + VERIFY( hash_value(path("a//b")) == hash_value(path("a/b")) ); + VERIFY( hash_value(path("a/")) == hash_value(path("a/.")) ); +} + +void +test02() +{ + for (const path& p : __gnu_test::test_paths) + { + path pp = p.native(); + VERIFY( hash_value(p) == hash_value(pp) ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/empty.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/empty.cc new file mode 100644 index 00000000000..b636f072619 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/empty.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const std::string& s : __gnu_test::test_paths) + { + VERIFY( s.empty() == path(s).empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_extension.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_extension.cc new file mode 100644 index 00000000000..1edee38112f --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_extension.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_extension() == !p.extension().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_filename.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_filename.cc new file mode 100644 index 00000000000..308f78762ab --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_filename.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_filename() == !p.filename().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_parent_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_parent_path.cc new file mode 100644 index 00000000000..5068ebb04b9 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_parent_path.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_parent_path() == !p.parent_path().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_relative_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_relative_path.cc new file mode 100644 index 00000000000..13ab666ae4a --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_relative_path.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_relative_path() == !p.relative_path().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_directory.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_directory.cc new file mode 100644 index 00000000000..16df83c0ab1 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_directory.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_root_directory() == !p.root_directory().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_name.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_name.cc new file mode 100644 index 00000000000..e8f2de70693 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_name.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_root_name() == !p.root_name().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_path.cc new file mode 100644 index 00000000000..fed615fb579 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_root_path.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_root_path() == !p.root_path().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_stem.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_stem.cc new file mode 100644 index 00000000000..eab381a227b --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/has_stem.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.has_stem() == !p.stem().empty() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/query/is_relative.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/query/is_relative.cc new file mode 100644 index 00000000000..4512f6e747f --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/query/is_relative.cc @@ -0,0 +1,43 @@ +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +// Copyright (C) 2014-2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 8.4.9 path decomposition [path.decompose] + +#include +#include +#include +#include + +using std::experimental::filesystem::path; + +void +test01() +{ + for (const path& p : __gnu_test::test_paths) + { + VERIFY( p.is_relative() == !p.is_absolute() ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp index 56ca89617ab..b5fb3e3877f 100644 --- a/libstdc++-v3/testsuite/lib/dg-options.exp +++ b/libstdc++-v3/testsuite/lib/dg-options.exp @@ -223,6 +223,15 @@ proc dg-require-little-endian { args } { return } +proc dg-require-filesystem-ts { args } { + if { ![ check_v3_target_filesystem_ts ] } { + upvar dg-do-what dg-do-what + set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"] + return + } + return +} + proc add_options_for_no_pch { flags } { # This forces any generated and possibly included PCH to be invalid. return "-D__GLIBCXX__=99999999" diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp index d581a53e3c4..7ae4f3fc054 100644 --- a/libstdc++-v3/testsuite/lib/libstdc++.exp +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp @@ -1895,6 +1895,53 @@ proc check_v3_target_little_endian { } { return $et_little_endian } +proc check_v3_target_filesystem_ts { } { + global et_filesystem_ts + global tool + + if { ![info exists et_filesystem_ts_target_name] } { + set et_filesystem_ts_target_name "" + } + + # If the target has changed since we set the cached value, clear it. + set current_target [current_target_name] + if { $current_target != $et_filesystem_ts_target_name } { + verbose "check_v3_target_filesystem_ts: `$et_filesystem_ts_target_name'" 2 + set et_filesystem_ts_target_name $current_target + if [info exists et_filesystem_ts] { + verbose "check_v3_target_filesystem_ts: removing cached result" 2 + unset et_filesystem_ts + } + } + + if [info exists et_filesystem_ts] { + verbose "check_v3_target_filesystem_ts: using cached result" 2 + } else { + set et_filesystem_ts 0 + + # Set up and preprocess a C++ test program that depends + # on debug mode activated. + set src filesystem_ts[pid].cc + + set f [open $src "w"] + puts $f "#include " + puts $f "#if ! __cpp_lib_experimental_filesystem" + puts $f "# error No Filesystem TS support" + puts $f "#endif" + close $f + + set lines [v3_target_compile $src /dev/null preprocess ""] + file delete $src + + if [string match "" $lines] { + # No error message, preprocessing succeeded. + set et_filesystem_ts 1 + } + } + verbose "check_v3_target_filesystem_ts: $et_filesystem_ts" 2 + return $et_filesystem_ts +} + set additional_prunes "" if { [info exists env(GCC_RUNTEST_PARALLELIZE_DIR)] \ diff --git a/libstdc++-v3/testsuite/util/testsuite_fs.h b/libstdc++-v3/testsuite/util/testsuite_fs.h new file mode 100644 index 00000000000..0fb3a459d93 --- /dev/null +++ b/libstdc++-v3/testsuite/util/testsuite_fs.h @@ -0,0 +1,67 @@ +// -*- C++ -*- +// Filesystem utils for the C++ library testsuite. +// +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . +// + +#ifndef _TESTSUITE_FS_H +#define _TESTSUITE_FS_H 1 + +#include +#include +#include + +namespace __gnu_test +{ +#define PATH_CHK(p1, p2, fn) \ + if ( p1.fn() != p2.fn() ) \ + throw std::experimental::filesystem::filesystem_error( #fn, p1, p2, \ + std::make_error_code(std::errc::invalid_argument) ) + + void + compare_paths(const std::experimental::filesystem::path& p1, + const std::experimental::filesystem::path& p2) + { + // std::cout << "Comparing " << p1 << " and " << p2 << std::endl; + PATH_CHK( p1, p2, string ); + PATH_CHK( p1, p2, empty ); + PATH_CHK( p1, p2, has_root_path ); + PATH_CHK( p1, p2, has_root_name ); + PATH_CHK( p1, p2, has_root_directory ); + PATH_CHK( p1, p2, has_relative_path ); + PATH_CHK( p1, p2, has_parent_path ); + PATH_CHK( p1, p2, has_filename ); + PATH_CHK( p1, p2, has_stem ); + PATH_CHK( p1, p2, has_extension ); + PATH_CHK( p1, p2, is_absolute ); + PATH_CHK( p1, p2, is_relative ); + auto d1 = std::distance(p1.begin(), p1.end()); + auto d2 = std::distance(p2.begin(), p2.end()); + if( d1 != d2 ) + throw std::experimental::filesystem::filesystem_error( + "distance(begin, end)", p1, p2, + std::make_error_code(std::errc::invalid_argument) ); + } + + const std::string test_paths[] = { + "", "/", "//", "/.", "/./", "/a", "/a/", "/a//", "/a/b/c/d", "/a//b", + "a", "a/b", "a/b/", "a/b/c", "a/b/c.d", "a/b/..", "a/b/c.", "a/b/.c" + }; + +} // namespace __gnu_test +#endif -- 2.30.2