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("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
add_executable(filesystem_test test/filesystem_test.cpp filesystem.h test/catch.hpp)
if(CMAKE_GENERATOR STREQUAL Xcode)
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()
add_subdirectory(test)
add_subdirectory(examples)

View File

@ -132,11 +132,50 @@ It's the version as decimal number `(major * 10000 + minor * 100 + patch)`.
## 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
head over to https://en.cppreference.com/w/cpp/filesystem for a description of
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
@ -292,6 +331,13 @@ to the expected behavior.
* Updated catch2 to v2.4.0.
* Refactored `fs.op.permissions` test to work with all tested `std::filesystem`
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)

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

@ -901,6 +901,26 @@ typedef basic_ofstream<wchar_t> wofstream;
typedef basic_fstream<char> fstream;
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
//-------------------------------------------------------------------------------------------------
@ -1181,6 +1201,26 @@ inline void postprocess_path_with_format(path::string_type& p, path::format fmt)
} // 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>
inline path::path(const Source& source, format fmt)
: _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()