summaryrefslogtreecommitdiff
path: root/Source/cmList.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmList.h')
-rw-r--r--Source/cmList.h1198
1 files changed, 1198 insertions, 0 deletions
diff --git a/Source/cmList.h b/Source/cmList.h
new file mode 100644
index 0000000000..d994ad3890
--- /dev/null
+++ b/Source/cmList.h
@@ -0,0 +1,1198 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#pragma once
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+#include <numeric>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/string_view>
+
+#include "cmValue.h"
+
+/**
+ * CMake lists management
+ *
+ * For all operations, input arguments (single value like cm::string_view or
+ * multiple values specified through pair of iterators) are, by default,
+ * expanded. The expansion can be controlled by the cmList::ExpandElements
+ * option.
+ *
+ * There is an exception to this rule. The following methods do not expand
+ * their argument: cmList::push_back, cmList::emplace and cmList::emplace_back.
+ */
+
+class cmList
+{
+public:
+ using container_type = std::vector<std::string>;
+
+ using value_type = container_type::value_type;
+ using allocator_type = container_type::allocator_type;
+ using index_type = int;
+ using size_type = container_type::size_type;
+ using difference_type = container_type::difference_type;
+ using reference = container_type::reference;
+ using const_reference = container_type::const_reference;
+ using iterator = container_type::iterator;
+ using const_iterator = container_type::const_iterator;
+ using reverse_iterator = container_type::reverse_iterator;
+ using const_reverse_iterator = container_type::const_reverse_iterator;
+
+ static const size_type npos = static_cast<size_type>(-1);
+
+ static cm::string_view element_separator;
+
+ enum class EmptyElements
+ {
+ No,
+ Yes,
+ };
+ enum class ExpandElements
+ {
+ No,
+ Yes,
+ };
+
+ cmList() = default;
+ cmList(const cmList&) = default;
+ cmList(cmList&&) = default;
+
+ cmList(cm::string_view value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->assign(value, expandElements, emptyElements);
+ }
+ cmList(cm::string_view value, EmptyElements emptyElements)
+ {
+ this->assign(value, ExpandElements::Yes, emptyElements);
+ }
+ cmList(cmValue list, ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (list) {
+ this->assign(*list, expandElements, emptyElements);
+ }
+ }
+ cmList(cmValue list, EmptyElements emptyElements)
+ : cmList(list, ExpandElements::Yes, emptyElements)
+ {
+ }
+ template <typename InputIterator>
+ cmList(InputIterator first, InputIterator last,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->assign(first, last, expandElements, emptyElements);
+ }
+ template <typename InputIterator>
+ cmList(InputIterator first, InputIterator last, EmptyElements emptyElements)
+ : cmList(first, last, ExpandElements::Yes, emptyElements)
+ {
+ }
+ cmList(const container_type& init,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ : cmList(init.begin(), init.end(), expandElements, emptyElements)
+ {
+ }
+ cmList(const container_type& init, EmptyElements emptyElements)
+ : cmList(init, ExpandElements::Yes, emptyElements)
+ {
+ }
+ cmList(container_type&& init,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ : cmList(std::make_move_iterator(init.begin()),
+ std::make_move_iterator(init.end()), expandElements,
+ emptyElements)
+ {
+ init.clear();
+ }
+ cmList(container_type&& init, EmptyElements emptyElements)
+ : cmList(std::move(init), ExpandElements::Yes, emptyElements)
+ {
+ }
+ cmList(std::initializer_list<std::string> init) { this->assign(init); }
+
+ ~cmList() = default;
+
+ cmList& operator=(const cmList&) = default;
+ cmList& operator=(cmList&&) = default;
+
+ cmList& operator=(cm::string_view value)
+ {
+ this->assign(value);
+ return *this;
+ }
+ cmList& operator=(cmValue value)
+ {
+ if (value) {
+ this->operator=(*value);
+ } else {
+ this->clear();
+ }
+
+ return *this;
+ }
+
+ cmList& operator=(const container_type& init)
+ {
+ this->assign(init);
+ return *this;
+ }
+ cmList& operator=(container_type&& init)
+ {
+ this->assign(std::move(init));
+
+ return *this;
+ }
+
+ cmList& operator=(std::initializer_list<std::string> init)
+ {
+ this->assign(init);
+ return *this;
+ }
+
+ void assign(cm::string_view value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->clear();
+ this->append(value, expandElements, emptyElements);
+ }
+ void assign(cm::string_view value, EmptyElements emptyElements)
+ {
+ this->assign(value, ExpandElements::Yes, emptyElements);
+ }
+ void assign(cmValue value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ this->assign(*value, expandElements, emptyElements);
+ } else {
+ this->clear();
+ }
+ }
+ void assign(cmValue value, EmptyElements emptyElements)
+ {
+ this->assign(value, ExpandElements::Yes, emptyElements);
+ }
+ template <typename InputIterator>
+ void assign(InputIterator first, InputIterator last,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->clear();
+ this->append(first, last, expandElements, emptyElements);
+ }
+ template <typename InputIterator>
+ void assign(InputIterator first, InputIterator last,
+ EmptyElements emptyElements)
+ {
+ this->assign(first, last, ExpandElements::Yes, emptyElements);
+ }
+ void assign(const cmList& init,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->assign(init.begin(), init.end(), expandElements, emptyElements);
+ }
+ void assign(const cmList& init, EmptyElements emptyElements)
+ {
+ this->assign(init, ExpandElements::Yes, emptyElements);
+ }
+ void assign(cmList&& init,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->assign(std::make_move_iterator(init.begin()),
+ std::make_move_iterator(init.end()), expandElements,
+ emptyElements);
+ init.clear();
+ }
+ void assign(cmList&& init, EmptyElements emptyElements)
+ {
+ this->assign(std::move(init), ExpandElements::Yes, emptyElements);
+ }
+ void assign(const container_type& init,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->assign(init.begin(), init.end(), expandElements, emptyElements);
+ }
+ void assign(const container_type& init, EmptyElements emptyElements)
+ {
+ this->assign(init, ExpandElements::Yes, emptyElements);
+ }
+ void assign(container_type&& init,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ this->assign(std::make_move_iterator(init.begin()),
+ std::make_move_iterator(init.end()), expandElements,
+ emptyElements);
+ init.clear();
+ }
+ void assign(container_type&& init, EmptyElements emptyElements)
+ {
+ this->assign(std::move(init), ExpandElements::Yes, emptyElements);
+ }
+ void assign(std::initializer_list<std::string> init)
+ {
+ this->assign(init.begin(), init.end());
+ }
+
+ // Conversions
+ std::string to_string() const
+ {
+ return this->join(cmList::element_separator);
+ }
+
+ operator container_type&() & noexcept { return this->Values; }
+ operator const container_type&() const& noexcept { return this->Values; }
+ operator container_type&&() && noexcept { return std::move(this->Values); }
+
+ // Element access
+ reference at(index_type pos)
+ {
+ return this->Values.at(this->ComputeIndex(pos));
+ }
+ const_reference at(index_type pos) const
+ {
+ return this->Values.at(this->ComputeIndex(pos));
+ }
+
+ reference operator[](index_type pos)
+ {
+ return this->Values[this->ComputeIndex(pos, false)];
+ }
+ const_reference operator[](index_type pos) const
+ {
+ return this->Values[this->ComputeIndex(pos, false)];
+ }
+
+ reference front() { return this->Values.front(); }
+ const_reference front() const { return this->Values.front(); }
+
+ reference back() { return this->Values.back(); }
+ const_reference back() const { return this->Values.back(); }
+
+ // extract sublist in range [first, last)
+ cmList sublist(const_iterator first, const_iterator last) const
+ {
+ return cmList{ first, last };
+ }
+ // Extract sublist in range [first, last)
+ // Throw std::out_of_range if pos is invalid
+ cmList sublist(size_type pos = 0, size_type length = npos) const;
+
+ // Returns the list of elements
+ // Throw std::out_of_range if any index is invalid
+ cmList get_items(std::initializer_list<index_type> indexes) const
+ {
+ return this->GetItems(
+ std::vector<index_type>{ indexes.begin(), indexes.end() });
+ }
+ template <typename InputIterator>
+ cmList get_items(InputIterator first, InputIterator last) const
+ {
+ return this->GetItems(std::vector<index_type>{ first, last });
+ }
+
+ size_type find(cm::string_view value) const;
+ size_type find(cmValue value) const
+ {
+ if (value) {
+ return this->find(*value);
+ }
+
+ return npos;
+ }
+
+ container_type& data() noexcept { return this->Values; }
+ const container_type& data() const noexcept { return this->Values; }
+
+ // Iterators
+ iterator begin() noexcept { return this->Values.begin(); }
+ const_iterator begin() const noexcept { return this->Values.begin(); }
+ const_iterator cbegin() const noexcept { return this->Values.cbegin(); }
+
+ iterator end() noexcept { return this->Values.end(); }
+ const_iterator end() const noexcept { return this->Values.end(); }
+ const_iterator cend() const noexcept { return this->Values.cend(); }
+
+ reverse_iterator rbegin() noexcept { return this->Values.rbegin(); }
+ const_reverse_iterator rbegin() const noexcept
+ {
+ return this->Values.rbegin();
+ }
+ const_reverse_iterator crbegin() const noexcept
+ {
+ return this->Values.crbegin();
+ }
+
+ reverse_iterator rend() noexcept { return this->Values.rend(); }
+ const_reverse_iterator rend() const noexcept { return this->Values.rend(); }
+ const_reverse_iterator crend() const noexcept
+ {
+ return this->Values.crend();
+ }
+
+ // Capacity
+ bool empty() const noexcept { return this->Values.empty(); }
+ size_type size() const noexcept { return this->Values.size(); }
+
+ // Modifiers
+ void clear() noexcept { this->Values.clear(); }
+
+ iterator insert(const_iterator pos, cm::string_view value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::Insert(pos, std::string(value), this->Values,
+ expandElements, emptyElements);
+ }
+ iterator insert(const_iterator pos, cm::string_view value,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, value, ExpandElements::Yes, emptyElements);
+ }
+ iterator insert(const_iterator pos, cmValue value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ return this->insert(pos, *value, expandElements, emptyElements);
+ }
+
+ auto delta = std::distance(this->cbegin(), pos);
+ return this->begin() + delta;
+ }
+ iterator insert(const_iterator pos, cmValue value,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, value, ExpandElements::Yes, emptyElements);
+ }
+ template <typename InputIterator>
+ iterator insert(const_iterator pos, InputIterator first, InputIterator last,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::Insert(pos, first, last, this->Values, expandElements,
+ emptyElements);
+ }
+ template <typename InputIterator>
+ iterator insert(const_iterator pos, InputIterator first, InputIterator last,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, first, last, ExpandElements::Yes, emptyElements);
+ }
+ iterator insert(const_iterator pos, const cmList& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->insert(pos, values.begin(), values.end(), expandElements,
+ emptyElements);
+ }
+ iterator insert(const_iterator pos, const cmList& values,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, values, ExpandElements::Yes, emptyElements);
+ }
+ iterator insert(const_iterator pos, cmList&& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ auto result = this->insert(pos, std::make_move_iterator(values.begin()),
+ std::make_move_iterator(values.end()),
+ expandElements, emptyElements);
+ values.clear();
+
+ return result;
+ }
+ iterator insert(const_iterator pos, cmList&& values,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, std::move(values), ExpandElements::Yes,
+ emptyElements);
+ }
+ iterator insert(const_iterator pos, const container_type& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->insert(pos, values.begin(), values.end(), expandElements,
+ emptyElements);
+ }
+ iterator insert(const_iterator pos, const container_type& values,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, values, ExpandElements::Yes, emptyElements);
+ }
+ iterator insert(const_iterator pos, container_type&& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ auto result = this->insert(pos, std::make_move_iterator(values.begin()),
+ std::make_move_iterator(values.end()),
+ expandElements, emptyElements);
+ values.clear();
+
+ return result;
+ }
+ iterator insert(const_iterator pos, container_type&& values,
+ EmptyElements emptyElements)
+ {
+ return this->insert(pos, std::move(values), ExpandElements::Yes,
+ emptyElements);
+ }
+ iterator insert(const_iterator pos, std::initializer_list<std::string> ilist)
+ {
+ return this->insert(pos, ilist.begin(), ilist.end());
+ }
+
+ iterator append(cm::string_view value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->insert(this->cend(), value, expandElements, emptyElements);
+ }
+ iterator append(cm::string_view value, EmptyElements emptyElements)
+ {
+ return this->append(value, ExpandElements::Yes, emptyElements);
+ }
+ iterator append(cmValue value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ return this->append(*value, expandElements, emptyElements);
+ }
+
+ return this->end();
+ }
+ iterator append(cmValue value, EmptyElements emptyElements)
+ {
+ return this->append(value, ExpandElements::Yes, emptyElements);
+ }
+ template <typename InputIterator>
+ iterator append(InputIterator first, InputIterator last,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->insert(this->cend(), first, last, expandElements,
+ emptyElements);
+ }
+ template <typename InputIterator>
+ iterator append(InputIterator first, InputIterator last,
+ EmptyElements emptyElements)
+ {
+ return this->append(first, last, ExpandElements::Yes, emptyElements);
+ }
+ iterator append(const cmList& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->append(values.begin(), values.end(), expandElements,
+ emptyElements);
+ }
+ iterator append(const cmList& values, EmptyElements emptyElements)
+ {
+ return this->append(values, ExpandElements::Yes, emptyElements);
+ }
+ iterator append(cmList&& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ auto result = this->append(std::make_move_iterator(values.begin()),
+ std::make_move_iterator(values.end()),
+ expandElements, emptyElements);
+ values.clear();
+
+ return result;
+ }
+ iterator append(cmList&& values, EmptyElements emptyElements)
+ {
+ return this->append(std::move(values), ExpandElements::Yes, emptyElements);
+ }
+ iterator append(const container_type& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->append(values.begin(), values.end(), expandElements,
+ emptyElements);
+ }
+ iterator append(const container_type& values, EmptyElements emptyElements)
+ {
+ return this->append(values, ExpandElements::Yes, emptyElements);
+ }
+ iterator append(container_type&& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ auto result = this->append(std::make_move_iterator(values.begin()),
+ std::make_move_iterator(values.end()),
+ expandElements, emptyElements);
+ values.clear();
+
+ return result;
+ }
+ iterator append(container_type&& values, EmptyElements emptyElements)
+ {
+ return this->append(std::move(values), ExpandElements::Yes, emptyElements);
+ }
+ iterator append(std::initializer_list<std::string> ilist)
+ {
+ return this->insert(this->cend(), ilist);
+ }
+
+ iterator prepend(cm::string_view value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->insert(this->cbegin(), value, expandElements, emptyElements);
+ }
+ iterator prepend(cm::string_view value, EmptyElements emptyElements)
+ {
+ return this->prepend(value, ExpandElements::Yes, emptyElements);
+ }
+ iterator prepend(cmValue value,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ return this->prepend(*value, expandElements, emptyElements);
+ }
+
+ return this->begin();
+ }
+ iterator prepend(cmValue value, EmptyElements emptyElements)
+ {
+ return this->prepend(value, ExpandElements::Yes, emptyElements);
+ }
+ template <typename InputIterator>
+ iterator prepend(InputIterator first, InputIterator last,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->insert(this->cbegin(), first, last, expandElements,
+ emptyElements);
+ }
+ template <typename InputIterator>
+ iterator prepend(InputIterator first, InputIterator last,
+ EmptyElements emptyElements)
+ {
+ return this->prepend(first, last, ExpandElements::Yes, emptyElements);
+ }
+ iterator prepend(const cmList& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->prepend(values.begin(), values.end(), expandElements,
+ emptyElements);
+ }
+ iterator prepend(const cmList& values, EmptyElements emptyElements)
+ {
+ return this->prepend(values, ExpandElements::Yes, emptyElements);
+ }
+ iterator prepend(cmList&& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ auto result = this->prepend(std::make_move_iterator(values.begin()),
+ std::make_move_iterator(values.end()),
+ expandElements, emptyElements);
+ values.clear();
+
+ return result;
+ }
+ iterator prepend(cmList&& values, EmptyElements emptyElements)
+ {
+ return this->prepend(std::move(values), ExpandElements::Yes,
+ emptyElements);
+ }
+ iterator prepend(const container_type& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return this->prepend(values.begin(), values.end(), expandElements,
+ emptyElements);
+ }
+ iterator prepend(const container_type& values, EmptyElements emptyElements)
+ {
+ return this->prepend(values, ExpandElements::Yes, emptyElements);
+ }
+ iterator prepend(container_type&& values,
+ ExpandElements expandElements = ExpandElements::Yes,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ auto result = this->prepend(std::make_move_iterator(values.begin()),
+ std::make_move_iterator(values.end()),
+ expandElements, emptyElements);
+ values.clear();
+
+ return result;
+ }
+ iterator prepend(container_type&& values, EmptyElements emptyElements)
+ {
+ return this->prepend(std::move(values), ExpandElements::Yes,
+ emptyElements);
+ }
+ iterator prepend(std::initializer_list<std::string> ilist)
+ {
+ return this->insert(this->cbegin(), ilist);
+ }
+
+ void push_back(cm::string_view value)
+ {
+ this->Values.push_back(std::string{ value });
+ }
+ void push_back(std::string&& value)
+ {
+ this->Values.push_back(std::move(value));
+ }
+
+ template <typename... Args>
+ iterator emplace(const_iterator pos, Args&&... args)
+ {
+ return this->Values.emplace(pos, std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ void emplace_back(Args&&... args)
+ {
+ this->Values.emplace_back(std::forward<Args>(args)...);
+ }
+
+ // Inserts elements in the list
+ // Throw std::out_of_range if index is invalid
+ template <typename InputIterator>
+ cmList& insert_items(index_type index, InputIterator first,
+ InputIterator last)
+ {
+ this->insert(this->begin() + this->ComputeInsertIndex(index), first, last);
+ return *this;
+ }
+ cmList& insert_items(index_type index,
+ std::initializer_list<std::string> values)
+ {
+ return this->insert_items(index, values.begin(), values.end());
+ }
+
+ iterator erase(const_iterator pos)
+ {
+ // convert const_iterator in iterator to please non standard c++11
+ // compilers (gcc 4.8 for example)
+ auto pos2 =
+ this->Values.begin() + std::distance(this->Values.cbegin(), pos);
+ return this->Values.erase(pos2);
+ }
+ iterator erase(const_iterator first, const_iterator last)
+ {
+ // convert const_iterator in iterator to please non standard c++11
+ // compilers (gcc 4.8 for example)
+ auto first2 =
+ this->Values.begin() + std::distance(this->Values.cbegin(), first);
+ auto last2 =
+ this->Values.begin() + std::distance(this->Values.cbegin(), last);
+ return this->Values.erase(first2, last2);
+ }
+
+ void pop_back() { this->Values.pop_back(); }
+ void pop_front() { this->Values.erase(this->begin()); }
+
+ // Removes elements from the list
+ // Throw std::out_of_range if any index is invalid
+ cmList& remove_items(std::initializer_list<index_type> indexes)
+ {
+ return this->RemoveItems(
+ std::vector<index_type>{ indexes.begin(), indexes.end() });
+ }
+ cmList& remove_items(std::initializer_list<std::string> values)
+ {
+ return this->RemoveItems(
+ std::vector<std::string>{ values.begin(), values.end() });
+ }
+ template <typename InputIterator>
+ cmList& remove_items(InputIterator first, InputIterator last)
+ {
+ return this->RemoveItems(
+ std::vector<typename InputIterator::value_type>{ first, last });
+ }
+
+ cmList& remove_duplicates();
+
+ enum class FilterMode
+ {
+ INCLUDE,
+ EXCLUDE
+ };
+ // Includes or removes items from the list
+ // Throw std::invalid_argument if regular expression is invalid
+ cmList& filter(cm::string_view regex, FilterMode mode);
+
+ cmList& reverse()
+ {
+ std::reverse(this->Values.begin(), this->Values.end());
+ return *this;
+ }
+
+ struct SortConfiguration
+ {
+ enum class OrderMode
+ {
+ DEFAULT,
+ ASCENDING,
+ DESCENDING,
+ } Order = OrderMode::DEFAULT;
+
+ enum class CompareMethod
+ {
+ DEFAULT,
+ STRING,
+ FILE_BASENAME,
+ NATURAL,
+ } Compare = CompareMethod::DEFAULT;
+
+ enum class CaseSensitivity
+ {
+ DEFAULT,
+ SENSITIVE,
+ INSENSITIVE,
+ } Case = CaseSensitivity::DEFAULT;
+
+ // declare the default constructor to work-around clang bug
+ SortConfiguration();
+
+ SortConfiguration(OrderMode order, CompareMethod compare,
+ CaseSensitivity caseSensitivity)
+ : Order(order)
+ , Compare(compare)
+ , Case(caseSensitivity)
+ {
+ }
+ };
+ cmList& sort(const SortConfiguration& config = SortConfiguration{});
+
+ // exception raised on error during transform operations
+ class transform_error : public std::runtime_error
+ {
+ public:
+ transform_error(const std::string& error)
+ : std::runtime_error(error)
+ {
+ }
+ };
+
+ class TransformSelector
+ {
+ public:
+ using index_type = cmList::index_type;
+
+ // define some structs used as template selector
+ struct AT;
+ struct FOR;
+ struct REGEX;
+
+ virtual ~TransformSelector() = default;
+
+ virtual const std::string& GetTag() = 0;
+
+ // method NEW is used to allocate a selector of the needed type.
+ // For example:
+ // cmList::TransformSelector::New<AT>({1, 2, 5, 6});
+ // or
+ // cmList::TransformSelector::New<REGEX>("^XX.*");
+ template <typename Type>
+ static std::unique_ptr<TransformSelector> New(
+ std::initializer_list<index_type>);
+ template <typename Type>
+ static std::unique_ptr<TransformSelector> New(
+ std::vector<index_type> const&);
+ template <typename Type>
+ static std::unique_ptr<TransformSelector> New(std::vector<index_type>&&);
+
+ template <typename Type>
+ static std::unique_ptr<TransformSelector> New(std::string const&);
+ template <typename Type>
+ static std::unique_ptr<TransformSelector> New(std::string&&);
+
+ private:
+ static std::unique_ptr<TransformSelector> NewAT(
+ std::initializer_list<index_type> init);
+ static std::unique_ptr<TransformSelector> NewAT(
+ std::vector<index_type> const& init);
+ static std::unique_ptr<TransformSelector> NewAT(
+ std::vector<index_type>&& init);
+
+ static std::unique_ptr<TransformSelector> NewFOR(
+ std::initializer_list<index_type> init);
+ static std::unique_ptr<TransformSelector> NewFOR(
+ std::vector<index_type> const& init);
+ static std::unique_ptr<TransformSelector> NewFOR(
+ std::vector<index_type>&& init);
+
+ static std::unique_ptr<TransformSelector> NewREGEX(
+ std::string const& init);
+ static std::unique_ptr<TransformSelector> NewREGEX(std::string&& init);
+ };
+
+ enum class TransformAction
+ {
+ APPEND,
+ PREPEND,
+ TOLOWER,
+ TOUPPER,
+ STRIP,
+ GENEX_STRIP,
+ REPLACE
+ };
+
+ // Transforms the list by applying an action
+ // Throw std::transform_error is any of arguments specified are invalid
+ cmList& transform(TransformAction action,
+ std::unique_ptr<TransformSelector> = {});
+ cmList& transform(TransformAction action, std::string const& arg,
+ std::unique_ptr<TransformSelector> = {});
+ cmList& transform(TransformAction action, std::string const& arg1,
+ std::string const& arg2,
+ std::unique_ptr<TransformSelector> = {});
+ cmList& transform(TransformAction action,
+ std::vector<std::string> const& args,
+ std::unique_ptr<TransformSelector> = {});
+
+ std::string join(cm::string_view glue) const;
+
+ void swap(cmList& other) noexcept { this->Values.swap(other.Values); }
+
+ // static members
+ // ==============
+ // these methods can be used to store CMake list expansion directly in a
+ // std::vector.
+ static void assign(cm::string_view value,
+ std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ container.clear();
+ cmList::append(value, container, emptyElements);
+ }
+ static void assign(cmValue value, std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ cmList::assign(*value, container, emptyElements);
+ } else {
+ container.clear();
+ }
+ }
+ template <typename InputIterator>
+ static void assign(InputIterator first, InputIterator last,
+ std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ container.clear();
+ cmList::append(first, last, container, emptyElements);
+ }
+
+ static std::vector<std::string>::iterator insert(
+ std::vector<std::string>::const_iterator pos, cm::string_view value,
+ std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::Insert(pos, std::string(value), container,
+ ExpandElements::Yes, emptyElements);
+ }
+ static std::vector<std::string>::iterator insert(
+ std::vector<std::string>::const_iterator pos, cmValue value,
+ std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ return cmList::insert(pos, *value, container, emptyElements);
+ }
+
+ auto delta = std::distance(container.cbegin(), pos);
+ return container.begin() + delta;
+ }
+ template <typename InputIterator>
+ static std::vector<std::string>::iterator insert(
+ std::vector<std::string>::const_iterator pos, InputIterator first,
+ InputIterator last, std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::Insert(pos, first, last, container, ExpandElements::Yes,
+ emptyElements);
+ }
+
+ static std::vector<std::string>::iterator append(
+ cm::string_view value, std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::insert(container.cend(), value, container, emptyElements);
+ }
+ static std::vector<std::string>::iterator append(
+ cmValue value, std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ return cmList::append(*value, container, emptyElements);
+ }
+
+ return container.end();
+ }
+ template <typename InputIterator>
+ static std::vector<std::string>::iterator append(
+ InputIterator first, InputIterator last,
+ std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::insert(container.cend(), first, last, container,
+ emptyElements);
+ }
+
+ static std::vector<std::string>::iterator prepend(
+ cm::string_view value, std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::insert(container.cbegin(), value, container, emptyElements);
+ }
+ static std::vector<std::string>::iterator prepend(
+ cmValue value, std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ if (value) {
+ return cmList::prepend(*value, container, emptyElements);
+ }
+
+ return container.begin();
+ }
+ template <typename InputIterator>
+ static std::vector<std::string>::iterator prepend(
+ InputIterator first, InputIterator last,
+ std::vector<std::string>& container,
+ EmptyElements emptyElements = EmptyElements::No)
+ {
+ return cmList::insert(container.cbegin(), first, last, container,
+ emptyElements);
+ }
+
+ // The following methods offer the possibility to extend a CMake list
+ // but without any intermediate expansion. So the operation is simply a
+ // string concatenation with special handling for the CMake list item
+ // separator
+ static std::string& append(cm::string_view value, std::string& list);
+ template <typename InputIterator>
+ static std::string& append(InputIterator first, InputIterator last,
+ std::string& list)
+ {
+ if (first == last) {
+ return list;
+ }
+
+ return cmList::append(cm::string_view{ std::accumulate(
+ std::next(first), last, *first,
+ [](std::string a, const std::string& b) {
+ return std::move(a) +
+ std::string(cmList::element_separator) + b;
+ }) },
+ list);
+ }
+
+ static std::string& prepend(cm::string_view value, std::string& list);
+ template <typename InputIterator>
+ static std::string& prepend(InputIterator first, InputIterator last,
+ std::string& list)
+ {
+ if (first == last) {
+ return list;
+ }
+
+ return cmList::prepend(cm::string_view{ std::accumulate(
+ std::next(first), last, *first,
+ [](std::string a, const std::string& b) {
+ return std::move(a) +
+ std::string(cmList::element_separator) + b;
+ }) },
+ list);
+ }
+
+ // Non-members
+ // ===========
+ friend inline bool operator==(const cmList& lhs, const cmList& rhs) noexcept
+ {
+ return lhs.Values == rhs.Values;
+ }
+ friend inline bool operator!=(const cmList& lhs, const cmList& rhs) noexcept
+ {
+ return lhs.Values != rhs.Values;
+ }
+
+private:
+ size_type ComputeIndex(index_type pos, bool boundCheck = true) const;
+ size_type ComputeInsertIndex(index_type pos, bool boundCheck = true) const;
+
+ cmList GetItems(std::vector<index_type>&& indexes) const;
+
+ cmList& RemoveItems(std::vector<index_type>&& indexes);
+ cmList& RemoveItems(std::vector<std::string>&& items);
+
+ static container_type::iterator Insert(container_type::const_iterator pos,
+ std::string&& value,
+ container_type& container,
+ ExpandElements expandElements,
+ EmptyElements emptyElements);
+ static container_type::iterator Insert(container_type::const_iterator pos,
+ const std::string& value,
+ container_type& container,
+ ExpandElements expandElements,
+ EmptyElements emptyElements)
+ {
+ auto tmp = value;
+ return cmList::Insert(pos, std::move(tmp), container, expandElements,
+ emptyElements);
+ }
+ template <typename InputIterator>
+ static container_type::iterator Insert(container_type::const_iterator pos,
+ InputIterator first,
+ InputIterator last,
+ container_type& container,
+ ExpandElements expandElements,
+ EmptyElements emptyElements)
+ {
+ auto delta = std::distance(container.cbegin(), pos);
+
+ if (first == last) {
+ return container.begin() + delta;
+ }
+
+ auto insertPos = container.begin() + delta;
+ if (expandElements == ExpandElements::Yes) {
+ for (; first != last; ++first) {
+ auto size = container.size();
+ insertPos = cmList::Insert(insertPos, *first, container,
+ expandElements, emptyElements);
+ insertPos += container.size() - size;
+ }
+ } else {
+ for (; first != last; ++first) {
+ if (!first->empty() || emptyElements == EmptyElements::Yes) {
+ insertPos = container.insert(insertPos, *first);
+ insertPos++;
+ }
+ }
+ }
+
+ return container.begin() + delta;
+ }
+
+ container_type Values;
+};
+
+// specializations for cmList::TransformSelector allocators
+// ========================================================
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::AT>(
+ std::initializer_list<index_type> init)
+{
+ return cmList::TransformSelector::NewAT(init);
+}
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::AT>(
+ std::vector<index_type> const& init)
+{
+ return cmList::TransformSelector::NewAT(init);
+}
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::AT>(
+ std::vector<index_type>&& init)
+{
+ return cmList::TransformSelector::NewAT(std::move(init));
+}
+
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::FOR>(
+ std::initializer_list<index_type> init)
+{
+ return cmList::TransformSelector::NewFOR(init);
+}
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::FOR>(
+ std::vector<index_type> const& init)
+{
+ return cmList::TransformSelector::NewFOR(init);
+}
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::FOR>(
+ std::vector<index_type>&& init)
+{
+ return cmList::TransformSelector::NewFOR(std::move(init));
+}
+
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::REGEX>(
+ std::string const& init)
+{
+ return cmList::TransformSelector::NewREGEX(init);
+}
+template <>
+inline std::unique_ptr<cmList::TransformSelector>
+cmList::TransformSelector::New<cmList::TransformSelector::REGEX>(
+ std::string&& init)
+{
+ return cmList::TransformSelector::NewREGEX(std::move(init));
+}
+
+// Non-member functions
+// ====================
+inline std::vector<std::string>& operator+=(std::vector<std::string>& l,
+ const cmList& r)
+{
+ l.insert(l.end(), r.begin(), r.end());
+ return l;
+}
+inline std::vector<std::string>& operator+=(std::vector<std::string>& l,
+ cmList&& r)
+{
+ std::move(r.begin(), r.end(), std::back_inserter(l));
+ r.clear();
+
+ return l;
+}
+
+namespace cm {
+inline void erase(cmList& list, const std::string& value)
+{
+ list.erase(std::remove(list.begin(), list.end(), value), list.end());
+}
+
+template <typename Predicate>
+inline void erase_if(cmList& list, Predicate pred)
+{
+ list.erase(std::remove_if(list.begin(), list.end(), pred), list.end());
+}
+}
+
+namespace srd {
+inline void swap(cmList& lhs, cmList& rhs) noexcept
+{
+ lhs.swap(rhs);
+}
+}