From 51b0d45d9120d4bca5c7285d5e6b2f80db5a8310 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 17 Apr 2023 12:32:18 +0200 Subject: cmExpandList and cmExpandLists rely on cmList class --- Source/cmList.h | 56 +++++++++++++++++++++++++++++++++++-- Source/cmStringAlgorithms.cxx | 64 ------------------------------------------- Source/cmStringAlgorithms.h | 21 ++++++++------ 3 files changed, 66 insertions(+), 75 deletions(-) diff --git a/Source/cmList.h b/Source/cmList.h index d994ad3..8a1cb8e 100644 --- a/Source/cmList.h +++ b/Source/cmList.h @@ -16,6 +16,8 @@ #include #include +#include +#include #include "cmValue.h" @@ -1177,6 +1179,13 @@ inline std::vector& operator+=(std::vector& l, return l; } +namespace std { +inline void swap(cmList& lhs, cmList& rhs) noexcept +{ + lhs.swap(rhs); +} +} // namespace std + namespace cm { inline void erase(cmList& list, const std::string& value) { @@ -1188,11 +1197,52 @@ inline void erase_if(cmList& list, Predicate pred) { list.erase(std::remove_if(list.begin(), list.end(), pred), list.end()); } + +// +// Provide a special implementation of cm::append because, in this case, +// expansion must not be applied to the inserted elements +// +#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. +template ::value, int> = 0> +void append(cmList& v, InputIt first, InputIt last) +{ + v.append(first, last, cmList::ExpandElements::No); } -namespace srd { -inline void swap(cmList& lhs, cmList& rhs) noexcept +template ::value, int> = 0> +void append(cmList& v, Range const& r) { - lhs.swap(rhs); + v.append(r.begin(), r.end(), cmList::ExpandElements::No); +} + +#else + +template < + typename InputIt, + cm::enable_if_t< + cm::is_input_iterator::value && + std::is_convertible::value_type, + cmList::value_type>::value, + int> = 0> +void append(cmList& v, InputIt first, InputIt last) +{ + v.append(first, last, cmList::ExpandElements::No); } + +template ::value && + std::is_convertible::value, + int> = 0> +void append(cmList& v, Range const& r) +{ + v.append(r.begin(), r.end(), cmList::ExpandElements::No); } +#endif + +} // namespace cm diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx index 66bf383..968dd3c 100644 --- a/Source/cmStringAlgorithms.cxx +++ b/Source/cmStringAlgorithms.cxx @@ -80,70 +80,6 @@ std::vector cmTokenize(cm::string_view str, cm::string_view sep) return tokens; } -void cmExpandList(cm::string_view arg, std::vector& argsOut, - bool emptyArgs) -{ - // If argument is empty, it is an empty list. - if (!emptyArgs && arg.empty()) { - return; - } - - // if there are no ; in the name then just copy the current string - if (arg.find(';') == cm::string_view::npos) { - argsOut.emplace_back(arg); - return; - } - - std::string newArg; - // Break the string at non-escaped semicolons not nested in []. - int squareNesting = 0; - cm::string_view::iterator last = arg.begin(); - cm::string_view::iterator const cend = arg.end(); - for (cm::string_view::iterator c = last; c != cend; ++c) { - switch (*c) { - case '\\': { - // We only want to allow escaping of semicolons. Other - // escapes should not be processed here. - cm::string_view::iterator cnext = c + 1; - if ((cnext != cend) && *cnext == ';') { - newArg.append(last, c); - // Skip over the escape character - last = cnext; - c = cnext; - } - } break; - case '[': { - ++squareNesting; - } break; - case ']': { - --squareNesting; - } break; - case ';': { - // Break the string here if we are not nested inside square - // brackets. - if (squareNesting == 0) { - newArg.append(last, c); - // Skip over the semicolon - last = c + 1; - if (!newArg.empty() || emptyArgs) { - // Add the last argument if the string is not empty. - argsOut.push_back(newArg); - newArg.clear(); - } - } - } break; - default: { - // Just append this character. - } break; - } - } - newArg.append(last, cend); - if (!newArg.empty() || emptyArgs) { - // Add the last argument if the string is not empty. - argsOut.push_back(std::move(newArg)); - } -} - std::vector cmExpandedList(cm::string_view arg, bool emptyArgs) { std::vector argsOut; diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 9ea7491..20274e8 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -14,6 +14,7 @@ #include +#include "cmList.h" #include "cmRange.h" #include "cmValue.h" @@ -92,14 +93,20 @@ std::vector cmTokenize(cm::string_view str, cm::string_view sep); * Expand the ; separated string @a arg into multiple arguments. * All found arguments are appended to @a argsOut. */ -void cmExpandList(cm::string_view arg, std::vector& argsOut, - bool emptyArgs = false); +inline void cmExpandList(cm::string_view arg, + std::vector& argsOut, + bool emptyArgs = false) +{ + cmList::append(arg, argsOut, + emptyArgs ? cmList::EmptyElements::Yes + : cmList::EmptyElements::No); +} inline void cmExpandList(cmValue arg, std::vector& argsOut, bool emptyArgs = false) { - if (arg) { - cmExpandList(*arg, argsOut, emptyArgs); - } + cmList::append(arg, argsOut, + emptyArgs ? cmList::EmptyElements::Yes + : cmList::EmptyElements::No); } /** @@ -111,9 +118,7 @@ template void cmExpandLists(InputIt first, InputIt last, std::vector& argsOut) { - for (; first != last; ++first) { - cmExpandList(*first, argsOut); - } + cmList::append(first, last, argsOut); } /** -- cgit v0.12