diff --git a/CMakeLists.txt b/CMakeLists.txt index dd30683b..5869c628 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ if (NOT WIN32) io_posix.hpp library_posix.hpp library_posix.cpp + paths_posix.cpp posix/fwd.hpp posix/interface.hpp posix/interface.cpp @@ -152,6 +153,7 @@ if (WIN32) io_win32.hpp library_win32.cpp library_win32.hpp + paths_win32.cpp rand/system_win32.cpp rand/system_win32.hpp time_win32.cpp @@ -473,6 +475,7 @@ list ( parse/value.hpp parse/si.cpp parse/si.hpp + paths.hpp platform.hpp point.cpp point.hpp diff --git a/paths.hpp b/paths.hpp new file mode 100644 index 00000000..ae022a4c --- /dev/null +++ b/paths.hpp @@ -0,0 +1,17 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2020, Danny Robson + */ + +#pragma once + +#include + + +namespace cruft::paths { + std::filesystem::path + expand (std::filesystem::path const&); +} \ No newline at end of file diff --git a/paths_posix.cpp b/paths_posix.cpp new file mode 100644 index 00000000..ec97e0b7 --- /dev/null +++ b/paths_posix.cpp @@ -0,0 +1,32 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2020, Danny Robson + */ + +#include "paths.hpp" + +#include "posix/except.hpp" +#include "debug/assert.hpp" + +#include + +#include + + +/////////////////////////////////////////////////////////////////////////////// +std::filesystem::path +cruft::paths::expand (std::filesystem::path const &val) +{ + wordexp_t words; + posix::error::try_call (wordexp, val.c_str (), &words, WRDE_NOCMD | WRDE_UNDEF); + std::unique_ptr cleanup {&words, &wordfree}; + + if (words.we_wordc != 1) + throw std::runtime_error ("glob matches too many files"); + + CHECK_EQ (words.we_offs, 0u); + return words.we_wordv[0]; +} diff --git a/paths_win32.cpp b/paths_win32.cpp new file mode 100644 index 00000000..85c5a8b9 --- /dev/null +++ b/paths_win32.cpp @@ -0,0 +1,38 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2020, Danny Robson + */ + +#include "paths.hpp" + +#include "win32/windows.hpp" +#include "win32/except.hpp" + +#include + + +/////////////////////////////////////////////////////////////////////////////// +std::filesystem::path +cruft::paths::expand (std::filesystem::path const &val) +{ + auto const required_size = ExpandEnvironmentStringsW (val.native ().data (), nullptr, 0) + 1; + + std::wstring store (required_size, '\0'); + + auto const actual_size = ExpandEnvironmentStringsW ( + val.native ().data (), + store.data (), + store.size () + ); + + if (actual_size == 0) + win32::error::throw_code (); + if (actual_size > required_size) + throw std::runtime_error ("Unable to expand path"); + store.resize (actual_size); + + return store; +} \ No newline at end of file