diff options
Diffstat (limited to 'Utilities')
26 files changed, 830 insertions, 12 deletions
diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 0564540..22a3d5a 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -13,7 +13,7 @@ if(CMAKE_DOC_TARBALL) endif() add_custom_command( OUTPUT ${dir}.stamp - COMMAND cmake -E remove_directory ${dir} + COMMAND cmake -E rm -rf ${dir} COMMAND cmake -E tar xf ${CMAKE_DOC_TARBALL} COMMAND cmake -E touch ${dir}.stamp DEPENDS ${CMAKE_DOC_TARBALL} diff --git a/Utilities/GitSetup/setup-user b/Utilities/GitSetup/setup-user index 1af439c..0b98879 100755 --- a/Utilities/GitSetup/setup-user +++ b/Utilities/GitSetup/setup-user @@ -20,12 +20,12 @@ # Project configuration instructions: NONE for (( ; ; )); do - user_name=$(git config user.name || echo '') && - user_email=$(git config user.email || echo '') && - if test -n "$user_name" -a -n "$user_email"; then + ident="$(git var GIT_AUTHOR_IDENT 2>/dev/null | rev | cut -d' ' -f3- | rev)" + + if test -n "$ident"; then echo 'Your commits will record as Author: - '"$user_name <$user_email>"' + '"$ident"' ' && read -ep 'Is the author name and email address above correct? [Y/n] ' correct && if test "$correct" != "n" -a "$correct" != "N"; then diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index ef31e8b..3497b53 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -24,6 +24,7 @@ { include: [ "<bits/shared_ptr.h>", private, "<memory>", public ] }, { include: [ "<bits/std_function.h>", private, "<functional>", public ] }, { include: [ "<bits/refwrap.h>", private, "<functional>", public ] }, + { include: [ "<bits/std_abs.h>", private, "<stdlib.h>", public ] }, { include: [ "<bits/stdint-intn.h>", private, "<stdint.h>", public ] }, { include: [ "<bits/stdint-uintn.h>", private, "<stdint.h>", public ] }, { include: [ "<bits/time.h>", private, "<time.h>", public ] }, @@ -46,6 +47,8 @@ # HACK: iwyu suggests <ext/alloc_traits.h> and <memory> each time vector[] is used. # https://github.com/include-what-you-use/include-what-you-use/issues/166 { include: [ "<ext/alloc_traits.h>", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmFileLock> >::value_type", private, "<vector>", public ] }, + { symbol: [ "std::allocator_traits<std::allocator<cmFileLockPool::ScopePool> >::value_type", private, "<vector>", public ] }, { symbol: [ "std::allocator_traits<std::allocator<cmComputeComponentGraph::TarjanEntry> >::value_type", private, "<vector>", public ] }, { symbol: [ "std::allocator_traits<std::allocator<cmFortranFile> >::value_type", private, "<vector>", public ] }, { symbol: [ "std::allocator_traits<std::allocator<cmGraphEdgeList> >::value_type", private, "<vector>", public ] }, diff --git a/Utilities/Release/push.bash b/Utilities/Release/push.bash index 1c8efe9..a1c6651 100755 --- a/Utilities/Release/push.bash +++ b/Utilities/Release/push.bash @@ -50,6 +50,9 @@ if test -z "$dir"; then dir="v${version}" fi readonly dir +if ! test -d "${dest}/${dir}"; then + mkdir "${dest}/${dir}" +fi for f in cmake-${version}*; do if ! test -f "${f}"; then diff --git a/Utilities/Scripts/regenerate-lexers.bash b/Utilities/Scripts/regenerate-lexers.bash index 1b61b70..186802a 100755 --- a/Utilities/Scripts/regenerate-lexers.bash +++ b/Utilities/Scripts/regenerate-lexers.bash @@ -14,7 +14,8 @@ for lexer in \ CTestResourceGroups \ DependsJava \ Expr \ - Fortran + Fortran \ + GccDepfile do cxx_file=cm${lexer}Lexer.cxx h_file=cm${lexer}Lexer.h diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index d903dbe..f164fd0 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -191,6 +191,7 @@ _cmake_index_objs = { 'cpack_gen': _cmake_index_entry('cpack generator'), 'envvar': _cmake_index_entry('envvar'), 'generator': _cmake_index_entry('generator'), + 'guide': _cmake_index_entry('guide'), 'manual': _cmake_index_entry('manual'), 'module': _cmake_index_entry('module'), 'policy': _cmake_index_entry('policy'), @@ -251,7 +252,7 @@ class CMakeTransform(Transform): env = self.document.settings.env # Treat some documents as cmake domain objects. - objtype, sep, tail = env.docname.rpartition('/') + objtype, sep, tail = env.docname.partition('/') make_index_entry = _cmake_index_objs.get(objtype) if make_index_entry: title = self.parse_title(env.docname) @@ -373,6 +374,7 @@ class CMakeDomain(Domain): 'cpack_gen': ObjType('cpack_gen', 'cpack_gen'), 'envvar': ObjType('envvar', 'envvar'), 'generator': ObjType('generator', 'generator'), + 'guide': ObjType('guide', 'guide'), 'variable': ObjType('variable', 'variable'), 'module': ObjType('module', 'module'), 'policy': ObjType('policy', 'policy'), @@ -407,6 +409,7 @@ class CMakeDomain(Domain): 'cpack_gen': CMakeXRefRole(), 'envvar': CMakeXRefRole(), 'generator': CMakeXRefRole(), + 'guide': CMakeXRefRole(), 'variable': CMakeXRefRole(), 'module': CMakeXRefRole(), 'policy': CMakeXRefRole(), diff --git a/Utilities/Sphinx/create_identifiers.py b/Utilities/Sphinx/create_identifiers.py index 6716b48..b5cd914 100755 --- a/Utilities/Sphinx/create_identifiers.py +++ b/Utilities/Sphinx/create_identifiers.py @@ -25,6 +25,7 @@ for line in lines: ("envvar", "envvar"), ("variable", "variable"), ("generator", "generator"), + ("guide", "guide"), ("target property", "prop_tgt"), ("test property", "prop_test"), ("source file property", "prop_sf"), diff --git a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in index db8e536..5178fd8 100644 --- a/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in +++ b/Utilities/cmcurl/CMake/cmake_uninstall.cmake.in @@ -13,7 +13,7 @@ foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + "@CMAKE_COMMAND@" ARGS "-E rm -f \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index 60c8316..26a9aa9 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -281,7 +281,6 @@ IF(BZIP2_FOUND) ENDIF(USE_BZIP2_DLL) ENDIF(BZIP2_FOUND) MARK_AS_ADVANCED(CLEAR BZIP2_INCLUDE_DIR) -MARK_AS_ADVANCED(CLEAR BZIP2_LIBRARIES) # diff --git a/Utilities/cmlibarchive/libarchive/archive_pack_dev.c b/Utilities/cmlibarchive/libarchive/archive_pack_dev.c index 53bddd7..f8286d8 100644 --- a/Utilities/cmlibarchive/libarchive/archive_pack_dev.c +++ b/Utilities/cmlibarchive/libarchive/archive_pack_dev.c @@ -57,8 +57,12 @@ __RCSID("$NetBSD$"); #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> #endif -#ifdef HAVE_SYS_SYSMACROS_H +#if MAJOR_IN_MKDEV +#include <sys/mkdev.h> +#define HAVE_MAJOR +#elif MAJOR_IN_SYSMACROS #include <sys/sysmacros.h> +#define HAVE_MAJOR #endif #ifdef HAVE_UNISTD_H #include <unistd.h> diff --git a/Utilities/std/.gitattributes b/Utilities/std/.gitattributes index cd20549..ad5459d 100644 --- a/Utilities/std/.gitattributes +++ b/Utilities/std/.gitattributes @@ -1 +1,2 @@ -cm/* our-c-style +cm/** our-c-style +cmext/** our-c-style diff --git a/Utilities/std/cm/bits/erase_if.hxx b/Utilities/std/cm/bits/erase_if.hxx new file mode 100644 index 0000000..8952fb5 --- /dev/null +++ b/Utilities/std/cm/bits/erase_if.hxx @@ -0,0 +1,29 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#ifndef cm_bits_erase_if_hxx +#define cm_bits_erase_if_hxx + +namespace cm { +namespace internals { + +template <typename Container, typename Predicate> +void erase_if(Container& cont, Predicate pred) +{ + for (typename Container::iterator iter = cont.begin(), last = cont.end(); + iter != last;) { + if (pred(*iter)) { + iter = cont.erase(iter); + } else { + ++iter; + } + } +} + +} // namespace internals +} // namespace cm + +#endif diff --git a/Utilities/std/cm/deque b/Utilities/std/cm/deque new file mode 100644 index 0000000..4bb6725 --- /dev/null +++ b/Utilities/std/cm/deque @@ -0,0 +1,40 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_deque +#define cm_deque + +#include <algorithm> +#include <deque> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Allocator, typename V> +inline void erase(std::deque<T, Allocator>& cont, const V& value) +{ + cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end()); +} + +template <typename T, typename Allocator, typename Predicate> +inline void erase_if(std::deque<T, Allocator>& cont, Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/list b/Utilities/std/cm/list new file mode 100644 index 0000000..ba5d94a --- /dev/null +++ b/Utilities/std/cm/list @@ -0,0 +1,39 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_list +#define cm_list + +#include <list> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Allocator, typename V> +inline void erase(std::list<T, Allocator>& cont, const V& value) +{ + cont.remove_if([&](auto& elem) { return elem == value; }); +} + +template <typename T, typename Allocator, typename Predicate> +inline void erase_if(std::list<T, Allocator>& cont, Predicate pred) +{ + cont.remove_if(pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/map b/Utilities/std/cm/map new file mode 100644 index 0000000..e348dec --- /dev/null +++ b/Utilities/std/cm/map @@ -0,0 +1,44 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_map +#define cm_map + +#include <map> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename T, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::map<Key, T, Compare, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename T, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::multimap<Key, T, Compare, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/memory b/Utilities/std/cm/memory index 8ebded2..dd0f822 100644 --- a/Utilities/std/cm/memory +++ b/Utilities/std/cm/memory @@ -8,6 +8,8 @@ #include <memory> // IWYU pragma: export #if !defined(CMake_HAVE_CXX_MAKE_UNIQUE) +# include <cstddef> +# include <type_traits> # include <utility> #endif @@ -19,12 +21,45 @@ using std::make_unique; #else +namespace internals { + +template <typename T> +struct make_unique_if +{ + using single = std::unique_ptr<T>; +}; + +template <typename T> +struct make_unique_if<T[]> +{ + using unbound_array = std::unique_ptr<T[]>; +}; + +template <typename T, std::size_t N> +struct make_unique_if<T[N]> +{ + using bound_array = void; +}; +} + template <typename T, typename... Args> -std::unique_ptr<T> make_unique(Args&&... args) +typename internals::make_unique_if<T>::single make_unique(Args&&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } +template <typename T> +typename internals::make_unique_if<T>::unbound_array make_unique(std::size_t n) +{ + using E = typename std::remove_extent<T>::type; + + return std::unique_ptr<T>(new E[n]()); +} + +template <typename T, typename... Args> +typename internals::make_unique_if<T>::bound_array make_unique(Args&&...) = + delete; + #endif } // namespace cm diff --git a/Utilities/std/cm/set b/Utilities/std/cm/set new file mode 100644 index 0000000..56dd474 --- /dev/null +++ b/Utilities/std/cm/set @@ -0,0 +1,43 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_set +#define cm_set + +#include <set> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::set<Key, Compare, Allocator>& cont, Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename Compare, typename Allocator, + typename Predicate> +inline void erase_if(std::multiset<Key, Compare, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/string b/Utilities/std/cm/string new file mode 100644 index 0000000..cc4c796 --- /dev/null +++ b/Utilities/std/cm/string @@ -0,0 +1,42 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_string +#define cm_string + +#include <algorithm> +#include <string> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Traits, typename Allocator, typename V> +inline void erase(std::basic_string<T, Traits, Allocator>& cont, + const V& value) +{ + cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end()); +} + +template <typename T, typename Traits, typename Allocator, typename Predicate> +inline void erase_if(std::basic_string<T, Traits, Allocator>& cont, + Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/type_traits b/Utilities/std/cm/type_traits new file mode 100644 index 0000000..e32c2c6 --- /dev/null +++ b/Utilities/std/cm/type_traits @@ -0,0 +1,63 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_type_traits +#define cm_type_traits + +#include <type_traits> // IWYU pragma: export + +namespace cm { + +#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) + +// Miscellaneous transformations +template <bool B, typename T = void> +using enable_if_t = std::enable_if_t<B, T>; + +#else + +// Miscellaneous transformations +template <bool B, typename T = void> +using enable_if_t = typename std::enable_if<B, T>::type; + +#endif + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703) + +// Helper classes +using std::bool_constant; + +// Miscellaneous transformations +using std::invoke_result; +using std::invoke_result_t; + +using std::void_t; + +#else + +// Helper classes +template <bool B> +using bool_constant = std::integral_constant<bool, B>; + +// Miscellaneous transformations +template <typename F, typename... ArgTypes> +using invoke_result = std::result_of<F(ArgTypes...)>; + +template <class F, typename... ArgTypes> +using invoke_result_t = typename invoke_result<F, ArgTypes...>::type; + +template <typename... ArgTypes> +struct make_void +{ + typedef void type; +}; +template <typename... ArgTypes> +using void_t = typename make_void<ArgTypes...>::type; + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/unordered_map b/Utilities/std/cm/unordered_map new file mode 100644 index 0000000..5b8a456 --- /dev/null +++ b/Utilities/std/cm/unordered_map @@ -0,0 +1,45 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_unordered_map +#define cm_unordered_map + +#include <unordered_map> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename T, typename Hash, typename KeyEqual, + typename Allocator, typename Predicate> +inline void erase_if( + std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& cont, Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename T, typename Hash, typename KeyEqual, + typename Allocator, typename Predicate> +inline void erase_if( + std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/unordered_set b/Utilities/std/cm/unordered_set new file mode 100644 index 0000000..9debac4 --- /dev/null +++ b/Utilities/std/cm/unordered_set @@ -0,0 +1,45 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_unordered_set +#define cm_unordered_set + +#include <unordered_set> // IWYU pragma: export + +#include <cm/bits/erase_if.hxx> + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase_if; + +#else + +template <typename Key, typename Hash, typename KeyEqual, typename Allocator, + typename Predicate> +inline void erase_if(std::unordered_set<Key, Hash, KeyEqual, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +template <typename Key, typename Hash, typename KeyEqual, typename Allocator, + typename Predicate> +inline void erase_if( + std::unordered_multiset<Key, Hash, KeyEqual, Allocator>& cont, + Predicate pred) +{ + internals::erase_if(cont, pred); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cm/vector b/Utilities/std/cm/vector new file mode 100644 index 0000000..2dbe704 --- /dev/null +++ b/Utilities/std/cm/vector @@ -0,0 +1,40 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cm_vector +#define cm_vector + +#include <algorithm> +#include <vector> // IWYU pragma: export + +namespace cm { + +// should be updated when C++20 is finalized +#if (__cplusplus > 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703)) && \ + defined(__cpp_lib_erase_if) + +using std::erase; +using std::erase_if; + +#else + +template <typename T, typename Allocator, typename V> +inline void erase(std::vector<T, Allocator>& cont, const V& value) +{ + cont.erase(std::remove(cont.begin(), cont.end(), value), cont.end()); +} + +template <typename T, typename Allocator, typename Predicate> +inline void erase_if(std::vector<T, Allocator>& cont, Predicate pred) +{ + cont.erase(std::remove_if(cont.begin(), cont.end(), pred), cont.end()); +} + +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/algorithm b/Utilities/std/cmext/algorithm new file mode 100644 index 0000000..44e61f4 --- /dev/null +++ b/Utilities/std/cmext/algorithm @@ -0,0 +1,163 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_algorithm +#define cmext_algorithm + +#include <algorithm> +#include <iterator> +#include <memory> +#include <utility> + +#include <cm/type_traits> +#include <cmext/iterator> + +#if defined(__SUNPRO_CC) && defined(__sparc) +# include <list> +# include <vector> +#else +# include <cmext/type_traits> +#endif + +namespace cm { + +#if defined(__SUNPRO_CC) && defined(__sparc) +// Oracle DeveloperStudio C++ compiler on Solaris/Sparc fails to compile +// templates with constraints. +// So, on this platform, use only simple templates. +# define APPEND_TWO(C1, C2) \ + template <typename T, typename U> \ + void append(C1<std::unique_ptr<T>>& v, C2<std::unique_ptr<U>>&& r) \ + { \ + std::transform( \ + r.begin(), r.end(), std::back_inserter(v), \ + [](std::unique_ptr<U>& item) { return std::move(item); }); \ + r.clear(); \ + } \ + \ + template <typename T, typename U> \ + void append(C1<T*>& v, C2<std::unique_ptr<U>> const& r) \ + { \ + std::transform( \ + r.begin(), r.end(), std::back_inserter(v), \ + [](const std::unique_ptr<U>& item) { return item.get(); }); \ + } + +# define APPEND_ONE(C) \ + template <typename T, typename InputIt, \ + cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = \ + 0> \ + void append(C<T>& v, InputIt first, InputIt last) \ + { \ + v.insert(v.end(), first, last); \ + } \ + \ + template <typename T, typename Range, \ + cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0> \ + void append(C<T>& v, Range const& r) \ + { \ + v.insert(v.end(), r.begin(), r.end()); \ + } + +# define APPEND(C) \ + APPEND_TWO(C, C) \ + APPEND_ONE(C) + +# define APPEND_MIX(C1, C2) \ + APPEND_TWO(C1, C2) \ + APPEND_TWO(C2, C1) + +// For now, manage only support for std::vector and std::list. +// Other sequential container support can be added if needed. +APPEND(std::vector) +APPEND(std::list) +APPEND_MIX(std::vector, std::list) + +# undef APPEND +# undef APPEND_MIX +# undef APPEND_TWO +# undef APPEND_ONE + +#else + +template < + typename Container1, typename Container2, + cm::enable_if_t< + cm::is_sequence_container<Container1>::value && + cm::is_unique_ptr<typename Container1::value_type>::value && + cm::is_unique_ptr<typename Container2::value_type>::value && + std::is_convertible<typename Container2::value_type::pointer, + typename Container1::value_type::pointer>::value, + int> = 0> +void append(Container1& v, Container2&& r) +{ + std::transform( + r.begin(), r.end(), std::back_inserter(v), + [](typename Container2::value_type& item) { return std::move(item); }); + r.clear(); +} + +template <typename Container1, typename Container2, + cm::enable_if_t< + cm::is_sequence_container<Container1>::value && + std::is_pointer<typename Container1::value_type>::value && + cm::is_unique_ptr<typename Container2::value_type>::value && + std::is_convertible<typename Container2::value_type::pointer, + typename Container1::value_type>::value, + int> = 0> +# if defined(__SUNPRO_CC) +void append(Container1& v, Container2 const& r, detail::overload_selector<0>) +# else +void append(Container1& v, Container2 const& r) +# endif +{ + std::transform( + r.begin(), r.end(), std::back_inserter(v), + [](const typename Container2::value_type& item) { return item.get(); }); +} + +template < + typename Container, typename InputIt, + cm::enable_if_t< + cm::is_sequence_container<Container>::value && + cm::is_input_iterator<InputIt>::value && + std::is_convertible<typename std::iterator_traits<InputIt>::value_type, + typename Container::value_type>::value, + int> = 0> +void append(Container& v, InputIt first, InputIt last) +{ + v.insert(v.end(), first, last); +} + +template <typename Container, typename Range, + cm::enable_if_t< + cm::is_sequence_container<Container>::value && + cm::is_input_range<Range>::value && + !cm::is_unique_ptr<typename Container::value_type>::value && + !cm::is_unique_ptr<typename Range::value_type>::value && + std::is_convertible<typename Range::value_type, + typename Container::value_type>::value, + int> = 0> +# if defined(__SUNPRO_CC) +void append(Container& v, Range const& r, detail::overload_selector<1>) +# else +void append(Container& v, Range const& r) +# endif +{ + v.insert(v.end(), r.begin(), r.end()); +} + +# if defined(__SUNPRO_CC) +template <typename T, typename U> +void append(T& v, U const& r) +{ + cm::append(v, r, detail::overload_selector<1>{}); +} +# endif +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/iterator b/Utilities/std/cmext/iterator new file mode 100644 index 0000000..ffe94b1 --- /dev/null +++ b/Utilities/std/cmext/iterator @@ -0,0 +1,49 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_iterator +#define cmext_iterator + +#include <iterator> + +#include <cm/type_traits> + +namespace cm { + +// checks if a type is an iterator type +template <typename I> +using is_iterator = + std::is_integral<typename std::iterator_traits<I>::difference_type>; + +// checks if a type is an input iterator type +template <typename I> +using is_input_iterator = + std::is_base_of<std::input_iterator_tag, + typename std::iterator_traits<I>::iterator_category>; + +// checks if a type is a range type: must have a difference_type type +template <typename Range> +using is_range = cm::bool_constant< + cm::is_iterator<decltype(std::declval<const Range>().begin())>::value && + cm::is_iterator<decltype(std::declval<const Range>().end())>::value>; + +// checks if a type is an input range type: must have methods begin() and end() +// returning an input iterator +template <typename Range> +using is_input_range = +#if defined(_MSC_VER) && _MSC_VER < 1920 + // MS C++ is not able to evaluate complex type introspection, + // so use a simplified version + cm::is_input_iterator<typename Range::const_iterator>; +#else + cm::bool_constant< + cm::is_input_iterator<decltype( + std::declval<const Range>().begin())>::value && + cm::is_input_iterator<decltype(std::declval<const Range>().end())>::value>; +#endif + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/memory b/Utilities/std/cmext/memory new file mode 100644 index 0000000..50e79df --- /dev/null +++ b/Utilities/std/cmext/memory @@ -0,0 +1,40 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_memory +#define cmext_memory + +#include <typeinfo> + +#include <cm/type_traits> + +namespace cm { + +template <typename T, typename O, + cm::enable_if_t< + std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value, + int> = 0> +T& static_reference_cast(O& item) +{ + return *(static_cast<T*>(item.get())); +} +template <typename T, typename O, + cm::enable_if_t< + std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value, + int> = 0> +T& dynamic_reference_cast(O& item) +{ + auto p = dynamic_cast<T*>(item.get()); + + if (p == nullptr) { + throw std::bad_cast(); + } + + return *p; +} + +} // namespace cm + +#endif diff --git a/Utilities/std/cmext/type_traits b/Utilities/std/cmext/type_traits new file mode 100644 index 0000000..00984cb --- /dev/null +++ b/Utilities/std/cmext/type_traits @@ -0,0 +1,86 @@ +// -*-c++-*- +// vim: set ft=cpp: + +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmext_type_traits +#define cmext_type_traits + +#include <cm/type_traits> + +namespace cm { + +#if defined(__SUNPRO_CC) +// Oracle DeveloperStudio C++ compiler do not support overloaded templates with +// same signature but different constraints over template arguments +// (i.e. meta-programming). +// As a work-around, use a structure to avoid templates with same signature. +namespace detail { +template <int N> +struct overload_selector : overload_selector<N - 1> +{ +}; + +template <> +struct overload_selector<0> +{ +}; +} +#endif + +// type traits for managed pointer types +template <typename> +struct is_unique_ptr : std::false_type +{ +}; +template <typename T> +struct is_unique_ptr<std::unique_ptr<T>> : std::true_type +{ +}; + +// type traits for containers +template <typename, typename = void_t<>> +struct is_container : std::false_type +{ +}; +template <typename T> +struct is_container< + T, + cm::void_t<typename T::value_type, typename T::size_type, + typename T::difference_type, typename T::iterator>> + : std::true_type +{ +}; + +template <typename, typename = void_t<>> +struct is_associative_container : std::false_type +{ +}; +template <typename T> +struct is_associative_container< + T, cm::void_t<typename T::key_type, typename T::key_compare>> + : cm::is_container<T> +{ +}; + +template <typename, typename = void_t<>> +struct is_unordered_associative_container : std::false_type +{ +}; +template <typename T> +struct is_unordered_associative_container< + T, + cm::void_t<typename T::key_type, typename T::hasher, typename T::key_equal, + typename T::local_iterator>> : cm::is_container<T> +{ +}; + +template <typename T> +using is_sequence_container = + cm::bool_constant<cm::is_container<T>::value && + !cm::is_associative_container<T>::value && + !cm::is_unordered_associative_container<T>::value>; + +} // namespace cm + +#endif |