Restructured CMakeLists, added fs::u8arguments helper, added first example

This commit is contained in:
Steffen Schuemann 2018-09-29 12:49:12 +02:00
parent 3e6a1e1771
commit 1da3ae7864
6 changed files with 186 additions and 27 deletions

View File

@ -6,29 +6,5 @@ set(CMAKE_CXX_STANDARD 11)
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
add_executable(filesystem_test test/filesystem_test.cpp filesystem.h test/catch.hpp) add_subdirectory(test)
if(CMAKE_GENERATOR STREQUAL Xcode) add_subdirectory(examples)
add_executable(filesystem_test_cov test/filesystem_test.cpp filesystem.h test/catch.hpp)
target_compile_options(filesystem_test_cov PRIVATE "$<$<CONFIG:DEBUG>:--coverage>")
target_link_libraries(filesystem_test_cov PRIVATE --coverage)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
include_directories(/usr/local/opt/llvm/include)
link_directories(/usr/local/opt/llvm/lib)
add_executable(std_filesystem_test test/filesystem_test.cpp filesystem.h test/catch.hpp)
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
target_link_libraries(std_filesystem_test -lc++fs)
endif()
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
add_executable(std_filesystem_test test/filesystem_test.cpp filesystem.h test/catch.hpp)
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
target_link_libraries(std_filesystem_test -lstdc++fs)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
add_executable(std_filesystem_test test/filesystem_test.cpp filesystem.h test/catch.hpp)
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
endif()

View File

@ -132,11 +132,50 @@ It's the version as decimal number `(major * 10000 + minor * 100 + patch)`.
## Documentation ## Documentation
There is no documentation in this release, as any `std::filesystem` documentation There is almost no documentation in this release, as any `std::filesystem` documentation
would work, besides the few differences explained in the next section. So you might would work, besides the few differences explained in the next section. So you might
head over to https://en.cppreference.com/w/cpp/filesystem for a description of head over to https://en.cppreference.com/w/cpp/filesystem for a description of
the components of this library. the components of this library.
The only additions to the standard are documented here:
### `ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`
These are simple wrappers around `std::ifstream`, `std::ofstream` and `std::fstream`.
They simply add an `open()` method and a constuctor with an `ghc::filesystem::path`
argument as the `fstream` variants in C++17 have them.
### `ghc::filesystem::u8arguments`
This is a helper class that acts neutral on non-Windows platforms but on Windows it
fetches the command line arguments als Unicode strings from the OS with
```cpp
::CommandLineToArgvW(::GetCommandLineW(), &argc)
```
and then converts them to UTF-8, and replaces `argc` and `argv`. It is a guard-like
class that reverts its changes when going out of scope.
So basic usage is:
```cpp
namespace fs = ghc::filesystem;
int main(int argc, char* argv[])
{
fs::u8arguments u8guard(argc, argv);
// now use argc/argv as usual, they have utf-8 enconding on windows
// ...
return 0;
}
```
That way `argv` is UTF-8 encoded as long as the scope from `main` is valid.
## Differences ## Differences
@ -292,6 +331,13 @@ to the expected behavior.
* Updated catch2 to v2.4.0. * Updated catch2 to v2.4.0.
* Refactored `fs.op.permissions` test to work with all tested `std::filesystem` * Refactored `fs.op.permissions` test to work with all tested `std::filesystem`
implementations (gcc, clang, msvc++). implementations (gcc, clang, msvc++).
* Added helper class `ghc::filesystem::u8arguments` as `argv` converter, to
help follow the UTF-8 path on windows. Simply instantiate it with `argc` and
`argv` and it will fetch the Unicode version of the command line and convert
it to UTF-8. The destructor reverts the change.
* Added `examples` folder with hopefully some usefull example usage. Examples are
tested (and build) with `ghc::filesystem` and C++17 `std::filesystem` when
available.
### [v1.0.1](https://github.com/gulrak/filesystem/tree/v1.0.1) ### [v1.0.1](https://github.com/gulrak/filesystem/tree/v1.0.1)

17
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
add_executable(fs_dir dir.cpp ../filesystem.h)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
add_executable(std_fs_dir dir.cpp)
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17)
target_link_libraries(std_fs_dir -lc++fs)
endif()
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
add_executable(std_fs_dir dir.cpp)
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17)
target_link_libraries(std_fs_dir -lstdc++fs)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
add_executable(std_fs_dir dir.cpp)
set_property(TARGET std_fs_dir PROPERTY CXX_STANDARD 17)
endif()

53
examples/dir.cpp Normal file
View File

@ -0,0 +1,53 @@
#include <iostream>
#include <iomanip>
#include <chrono>
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include) && __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include "../filesystem.h"
namespace fs = ghc::filesystem;
#endif
template<typename TP>
std::time_t to_time_t(TP tp)
{
// Based on trick from: Nico Josuttis, C++17 - The Complete Guide
return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + (tp - TP::clock::now()));
}
static std::string perm_to_str(fs::perms prms)
{
std::string result;
result.reserve(6);
for(int i = 0; i < 9; ++i) {
result = ((static_cast<int>(prms) & (1<<i)) ? "xwrxwrxwr"[i] : '-') + result;
}
return result;
}
int main(int argc, char* argv[])
{
#ifdef GHC_FILESYSTEM_VERSION
fs::u8arguments u8guard(argc, argv);
#endif
if(argc > 2) {
std::cerr << "USAGE: dir <path>" << std::endl;
exit(1);
}
fs::path dir{"."};
if(argc == 2) {
dir = fs::u8path(argv[1]);
}
for(auto de : fs::directory_iterator(dir)) {
auto ft = to_time_t(de.last_write_time());
auto ftm = *std::localtime(&ft);
std::cout << (de.is_directory() ? "d" : "-") << perm_to_str(de.symlink_status().permissions()) << " "
<< std::setw(8) << (de.is_directory() ? "-" : std::to_string(de.file_size())) << " "
<< std::put_time(&ftm, "%Y-%m-%d %H:%M:%S") << " "
<< de.path().filename().string()
<< std::endl;
}
return 0;
}

View File

@ -900,6 +900,26 @@ typedef basic_ofstream<char> ofstream;
typedef basic_ofstream<wchar_t> wofstream; typedef basic_ofstream<wchar_t> wofstream;
typedef basic_fstream<char> fstream; typedef basic_fstream<char> fstream;
typedef basic_fstream<wchar_t> wfstream; typedef basic_fstream<wchar_t> wfstream;
class u8arguments {
public:
u8arguments(int& argc, char**& argv);
~u8arguments()
{
_refargc = _argc;
_refargv = _argv;
}
private:
int _argc;
char** _argv;
int& _refargc;
char**& _refargv;
#ifdef GHC_OS_WINDOWS
std::vector<std::string> _args;
std::vector<char*> _argp;
#endif
};
//------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------
// Implementation // Implementation
@ -1181,6 +1201,26 @@ inline void postprocess_path_with_format(path::string_type& p, path::format fmt)
} // namespace detail } // namespace detail
inline u8arguments::u8arguments(int& argc, char**& argv)
: _argc(argc)
, _argv(argv)
, _refargc(argc)
, _refargv(argv)
{
#ifdef GHC_OS_WINDOWS
LPWSTR* p;
p = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
_args.reserve(argc);
_argp.reserve(argc);
for (size_t i = 0; i < argc; ++i) {
_args.push_back(detail::toUtf8(std::wstring(p[i])));
_argp.push_back((char*)_args[i].data());
}
argv = _argp.data();
::LocalFree(p);
#endif
}
template <class Source, typename> template <class Source, typename>
inline path::path(const Source& source, format fmt) inline path::path(const Source& source, format fmt)
: _path(source) : _path(source)

27
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,27 @@
add_executable(filesystem_test filesystem_test.cpp ../filesystem.h catch.hpp)
if(CMAKE_GENERATOR STREQUAL Xcode)
add_executable(filesystem_test_cov filesystem_test.cpp ../filesystem.h catch.hpp)
target_compile_options(filesystem_test_cov PRIVATE "$<$<CONFIG:DEBUG>:--coverage>")
target_link_libraries(filesystem_test_cov PRIVATE --coverage)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
include_directories(/usr/local/opt/llvm/include)
link_directories(/usr/local/opt/llvm/lib)
add_executable(std_filesystem_test filesystem_test.cpp ../filesystem.h catch.hpp)
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
target_link_libraries(std_filesystem_test -lc++fs)
endif()
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
add_executable(std_filesystem_test filesystem_test.cpp ../filesystem.h catch.hpp)
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
target_link_libraries(std_filesystem_test -lstdc++fs)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
add_executable(std_filesystem_test filesystem_test.cpp ../filesystem.h catch.hpp)
set_property(TARGET std_filesystem_test PROPERTY CXX_STANDARD 17)
target_compile_definitions(std_filesystem_test PRIVATE USE_STD_FS)
endif()