| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #pragma once | |
| #include "cmConfigure.h" // IWYU pragma: keep | |
| #include <algorithm> | |
| #include <cstddef> | |
| #include <functional> | |
| #include <initializer_list> | |
| #include <iterator> | |
| #include <memory> | |
| #include <stdexcept> | |
| #include <string> | |
| #include <utility> | |
| #include <vector> | |
| #include <cm/string_view> | |
| #include <cm/type_traits> | |
| #include <cmext/iterator> | |
| #include "cmValue.h" | |
| template <typename T> | |
| class BT; | |
| class cmMakefile; | |
| /** | |
| * CMake lists management | |
| * A CMake list is a string where list elements are separated by the ';' | |
| * character. | |
| * | |
| * 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 ate some exceptions to this rule: | |
| * * When the input argument is a cmList instance, the value is not expanded. | |
| * * 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 = std::ptrdiff_t; | |
| 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 size_type const 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(cmList const&) = 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) | |
| : cmList(value, ExpandElements::Yes, emptyElements) | |
| { | |
| } | |
| cmList(std::string const& value, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| this->assign(value, expandElements, emptyElements); | |
| } | |
| cmList(std::string const& value, EmptyElements emptyElements) | |
| : cmList(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(container_type const& init, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| : cmList(init.begin(), init.end(), expandElements, emptyElements) | |
| { | |
| } | |
| cmList(container_type const& 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=(cmList const&) = default; | |
| cmList& operator=(cmList&&) = default; | |
| cmList& operator=(cm::string_view value) | |
| { | |
| this->assign(value); | |
| return *this; | |
| } | |
| cmList& operator=(std::string const& value) | |
| { | |
| this->assign(value); | |
| return *this; | |
| } | |
| cmList& operator=(cmValue value) | |
| { | |
| if (value) { | |
| this->operator=(*value); | |
| } else { | |
| this->clear(); | |
| } | |
| return *this; | |
| } | |
| cmList& operator=(container_type const& 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(std::string const& value, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| this->clear(); | |
| this->append(value, expandElements, emptyElements); | |
| } | |
| void assign(std::string const& 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(cmList const& init, | |
| ExpandElements expandElements = ExpandElements::No, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| this->assign(init.begin(), init.end(), expandElements, emptyElements); | |
| } | |
| void assign(cmList const& init, EmptyElements emptyElements) | |
| { | |
| this->assign(init, ExpandElements::No, emptyElements); | |
| } | |
| void assign(cmList&& init, | |
| ExpandElements expandElements = ExpandElements::No, | |
| 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::No, emptyElements); | |
| } | |
| void assign(container_type const& init, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| this->assign(init.begin(), init.end(), expandElements, emptyElements); | |
| } | |
| void assign(container_type const& 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 container_type const&() const& noexcept { return this->Values; } | |
| operator container_type&&() && noexcept { return std::move(this->Values); } | |
| // Element access | |
| reference at(size_type pos) { return this->Values.at(pos); } | |
| const_reference at(size_type pos) const { return this->Values.at(pos); } | |
| reference operator[](size_type pos) { return this->Values[pos]; } | |
| const_reference operator[](size_type pos) const { return this->Values[pos]; } | |
| reference get_item(index_type pos) | |
| { | |
| return this->Values.at(this->ComputeIndex(pos)); | |
| } | |
| const_reference get_item(index_type pos) const | |
| { | |
| return this->Values.at(this->ComputeIndex(pos)); | |
| } | |
| 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, ExpandElements::No, EmptyElements::Yes }; | |
| } | |
| // 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; } | |
| container_type const& 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(this->Values, pos, std::string(value), | |
| 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, std::string const& value, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::Insert(this->Values, pos, value, expandElements, | |
| emptyElements); | |
| } | |
| iterator insert(const_iterator pos, std::string const& 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(this->Values, pos, first, last, 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, cmList const& values, | |
| ExpandElements expandElements = ExpandElements::No, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->insert(pos, values.begin(), values.end(), expandElements, | |
| emptyElements); | |
| } | |
| iterator insert(const_iterator pos, cmList const& values, | |
| EmptyElements emptyElements) | |
| { | |
| return this->insert(pos, values, ExpandElements::No, emptyElements); | |
| } | |
| iterator insert(const_iterator pos, cmList&& values, | |
| ExpandElements expandElements = ExpandElements::No, | |
| 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::No, | |
| emptyElements); | |
| } | |
| iterator insert(const_iterator pos, container_type const& values, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->insert(pos, values.begin(), values.end(), expandElements, | |
| emptyElements); | |
| } | |
| iterator insert(const_iterator pos, container_type const& 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(std::string const& value, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->insert(this->cend(), value, expandElements, emptyElements); | |
| } | |
| iterator append(std::string const& 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(cmList const& values, | |
| ExpandElements expandElements = ExpandElements::No, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->append(values.begin(), values.end(), expandElements, | |
| emptyElements); | |
| } | |
| iterator append(cmList const& values, EmptyElements emptyElements) | |
| { | |
| return this->append(values, ExpandElements::No, emptyElements); | |
| } | |
| iterator append(cmList&& values, | |
| ExpandElements expandElements = ExpandElements::No, | |
| 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::No, emptyElements); | |
| } | |
| iterator append(container_type const& values, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->append(values.begin(), values.end(), expandElements, | |
| emptyElements); | |
| } | |
| iterator append(container_type const& 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(std::string const& value, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->insert(this->cbegin(), value, expandElements, emptyElements); | |
| } | |
| iterator prepend(std::string const& 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(cmList const& values, | |
| ExpandElements expandElements = ExpandElements::No, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->prepend(values.begin(), values.end(), expandElements, | |
| emptyElements); | |
| } | |
| iterator prepend(cmList const& values, EmptyElements emptyElements) | |
| { | |
| return this->prepend(values, ExpandElements::No, emptyElements); | |
| } | |
| iterator prepend(cmList&& values, | |
| ExpandElements expandElements = ExpandElements::No, | |
| 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::No, emptyElements); | |
| } | |
| iterator prepend(container_type const& values, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return this->prepend(values.begin(), values.end(), expandElements, | |
| emptyElements); | |
| } | |
| iterator prepend(container_type const& 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(std::string const& value) { this->Values.push_back(value); } | |
| 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, | |
| ExpandElements expandElements = ExpandElements::Yes, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| auto const offset = | |
| static_cast<difference_type>(this->ComputeInsertIndex(index)); | |
| this->insert(this->begin() + offset, first, last, expandElements, | |
| emptyElements); | |
| return *this; | |
| } | |
| template <typename InputIterator> | |
| cmList& insert_items(index_type index, InputIterator first, | |
| InputIterator last, EmptyElements emptyElements) | |
| { | |
| this->insert(this->begin() + this->ComputeInsertIndex(index), first, last, | |
| ExpandElements::Yes, emptyElements); | |
| 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(); | |
| void resize(size_type count) { this->Values.resize(count); } | |
| void reserve(size_type count) { this->Values.reserve(count); } | |
| enum class FilterMode | |
| { | |
| INCLUDE, | |
| EXCLUDE | |
| }; | |
| // Includes or removes items from the list | |
| // Throw std::invalid_argument if regular expression is invalid or predicate | |
| // function is unknown / does not set its output variable | |
| cmList& filter(cm::string_view regex, FilterMode mode); | |
| cmList& filter(std::string const& functionName, FilterMode mode, | |
| cmMakefile& makefile); | |
| 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, | |
| COMPARATOR, | |
| } Compare = CompareMethod::DEFAULT; | |
| enum class CaseSensitivity | |
| { | |
| DEFAULT, | |
| SENSITIVE, | |
| INSENSITIVE, | |
| } Case = CaseSensitivity::DEFAULT; | |
| std::string ComparatorFunction; | |
| // 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(SortConfiguration config = SortConfiguration{}); | |
| cmList& sort(SortConfiguration config, cmMakefile& makefile); | |
| cmList& sort( | |
| SortConfiguration config, | |
| std::function<bool(std::string const&, std::string const&)> comparator); | |
| // exception raised on error during transform operations | |
| class transform_error : public std::runtime_error | |
| { | |
| public: | |
| transform_error(std::string const& 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; | |
| struct PREDICATE; | |
| virtual ~TransformSelector() = default; | |
| virtual std::string const& 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.*"); | |
| static std::unique_ptr<TransformSelector> New(); | |
| 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&&); | |
| // NewPREDICATE is public (unlike NewAT/NewFOR/NewREGEX) because it takes | |
| // a cmMakefile& parameter that cannot be dispatched through the existing | |
| // New<Type>() templates. | |
| static std::unique_ptr<TransformSelector> NewPREDICATE( | |
| std::string const& functionName, cmMakefile& makefile); | |
| cmMakefile* Makefile = nullptr; | |
| 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, | |
| APPLY | |
| }; | |
| // 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> = {}); | |
| cmList& transform(TransformAction action, std::string const& arg, | |
| cmMakefile& makefile, | |
| std::unique_ptr<TransformSelector> = {}); | |
| // Return, for each element of this list, whether `selector` selects it. | |
| // Throws transform_error on a malformed selector (e.g. an out-of-range | |
| // index), like transform(). | |
| std::vector<bool> GetTransformSelection(TransformSelector& selector) const; | |
| std::string join(cm::string_view glue) const | |
| { | |
| return cmList::Join(this->Values, glue); | |
| } | |
| 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(std::vector<std::string>& container, | |
| cm::string_view value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| container.clear(); | |
| cmList::append(container, value, emptyElements); | |
| } | |
| static void assign(std::vector<std::string>& container, | |
| std::string const& value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| container.clear(); | |
| cmList::append(container, value, emptyElements); | |
| } | |
| static void assign(std::vector<std::string>& container, cmValue value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| if (value) { | |
| cmList::assign(container, *value, emptyElements); | |
| } else { | |
| container.clear(); | |
| } | |
| } | |
| template <typename InputIterator> | |
| static void assign(std::vector<std::string>& container, InputIterator first, | |
| InputIterator last, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| container.clear(); | |
| cmList::append(container, first, last, emptyElements); | |
| } | |
| static std::vector<std::string>::iterator insert( | |
| std::vector<std::string>& container, | |
| std::vector<std::string>::const_iterator pos, cm::string_view value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::Insert(container, pos, std::string(value), | |
| ExpandElements::Yes, emptyElements); | |
| } | |
| static std::vector<std::string>::iterator insert( | |
| std::vector<std::string>& container, | |
| std::vector<std::string>::const_iterator pos, std::string const& value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::Insert(container, pos, value, ExpandElements::Yes, | |
| emptyElements); | |
| } | |
| static std::vector<std::string>::iterator insert( | |
| std::vector<std::string>& container, | |
| std::vector<std::string>::const_iterator pos, cmValue value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| if (value) { | |
| return cmList::insert(container, pos, *value, 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>& container, | |
| std::vector<std::string>::const_iterator pos, InputIterator first, | |
| InputIterator last, EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::Insert(container, pos, first, last, ExpandElements::Yes, | |
| emptyElements); | |
| } | |
| static std::vector<std::string>::iterator append( | |
| std::vector<std::string>& container, cm::string_view value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::insert(container, container.cend(), value, emptyElements); | |
| } | |
| static std::vector<std::string>::iterator append( | |
| std::vector<std::string>& container, std::string const& value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::insert(container, container.cend(), value, emptyElements); | |
| } | |
| static std::vector<std::string>::iterator append( | |
| std::vector<std::string>& container, cmValue value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| if (value) { | |
| return cmList::append(container, *value, emptyElements); | |
| } | |
| return container.end(); | |
| } | |
| template <typename InputIterator> | |
| static std::vector<std::string>::iterator append( | |
| std::vector<std::string>& container, InputIterator first, | |
| InputIterator last, EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::insert(container, container.cend(), first, last, | |
| emptyElements); | |
| } | |
| static std::vector<std::string>::iterator prepend( | |
| std::vector<std::string>& container, cm::string_view value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::insert(container, container.cbegin(), value, emptyElements); | |
| } | |
| static std::vector<std::string>::iterator prepend( | |
| std::vector<std::string>& container, std::string const& value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::insert(container, container.cbegin(), value, emptyElements); | |
| } | |
| static std::vector<std::string>::iterator prepend( | |
| std::vector<std::string>& container, cmValue value, | |
| EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| if (value) { | |
| return cmList::prepend(container, *value, emptyElements); | |
| } | |
| return container.begin(); | |
| } | |
| template <typename InputIterator> | |
| static std::vector<std::string>::iterator prepend( | |
| std::vector<std::string>& container, InputIterator first, | |
| InputIterator last, EmptyElements emptyElements = EmptyElements::No) | |
| { | |
| return cmList::insert(container, container.cbegin(), first, last, | |
| 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(std::string& list, std::string&& value); | |
| static std::string& append(std::string& list, cm::string_view value); | |
| template <typename InputIterator> | |
| static std::string& append(std::string& list, InputIterator first, | |
| InputIterator last) | |
| { | |
| if (first == last) { | |
| return list; | |
| } | |
| return cmList::append( | |
| list, cmList::Join(first, last, cmList::element_separator)); | |
| } | |
| static std::string& prepend(std::string& list, std::string&& value); | |
| static std::string& prepend(std::string& list, cm::string_view value); | |
| template <typename InputIterator> | |
| static std::string& prepend(std::string& list, InputIterator first, | |
| InputIterator last) | |
| { | |
| if (first == last) { | |
| return list; | |
| } | |
| return cmList::prepend( | |
| list, cmList::Join(first, last, cmList::element_separator)); | |
| } | |
| template <typename Range, | |
| cm::enable_if_t<cm::is_range<Range>::value, int> = 0> | |
| static std::string to_string(Range const& r) | |
| { | |
| return cmList::Join(r, cmList::element_separator); | |
| } | |
| // Non-members | |
| // =========== | |
| friend bool operator==(cmList const& lhs, cmList const& rhs) noexcept | |
| { | |
| return lhs.Values == rhs.Values; | |
| } | |
| friend bool operator!=(cmList const& lhs, cmList const& 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& container, | |
| container_type::const_iterator pos, | |
| std::string&& value, | |
| ExpandElements expandElements, | |
| EmptyElements emptyElements); | |
| static container_type::iterator Insert(container_type& container, | |
| container_type::const_iterator pos, | |
| std::string const& value, | |
| ExpandElements expandElements, | |
| EmptyElements emptyElements) | |
| { | |
| auto tmp = value; | |
| return cmList::Insert(container, pos, std::move(tmp), expandElements, | |
| emptyElements); | |
| } | |
| template <typename InputIterator> | |
| static container_type::iterator Insert(container_type& container, | |
| container_type::const_iterator pos, | |
| InputIterator first, | |
| InputIterator last, | |
| 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(container, insertPos, *first, | |
| expandElements, emptyElements); | |
| insertPos += static_cast<decltype(delta)>(container.size() - size); | |
| } | |
| } else { | |
| for (; first != last; ++first) { | |
| if (!(*first).empty() || emptyElements == EmptyElements::Yes) { | |
| insertPos = container.insert(insertPos, *first); | |
| ++insertPos; | |
| } | |
| } | |
| } | |
| return container.begin() + delta; | |
| } | |
| static std::string const& ToString(std::string const& s) { return s; } | |
| static std::string ToString(cm::string_view s) { return std::string{ s }; } | |
| static std::string const& ToString(BT<std::string> const&); | |
| template <typename Range> | |
| static std::string Join(Range const& r, cm::string_view glue) | |
| { | |
| if (cm::size(r) == 0) { | |
| return std::string{}; | |
| } | |
| return cmList::Join(std::begin(r), std::end(r), glue); | |
| } | |
| template <typename InputIterator> | |
| static std::string Join(InputIterator first, InputIterator last, | |
| cm::string_view glue) | |
| { | |
| if (first == last) { | |
| return std::string{}; | |
| } | |
| auto const sep = std::string{ glue }; | |
| std::string joined = cmList::ToString(*first); | |
| for (auto it = std::next(first); it != last; ++it) { | |
| joined += sep; | |
| joined += cmList::ToString(*it); | |
| } | |
| return joined; | |
| } | |
| 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, | |
| cmList const& 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; | |
| } | |
| inline void swap(cmList& lhs, cmList& rhs) noexcept | |
| { | |
| lhs.swap(rhs); | |
| } | |
| namespace cm { | |
| inline void erase(cmList& list, std::string const& 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()); | |
| } | |
| // | |
| // 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 <typename InputIt, | |
| cm::enable_if_t<cm::is_input_iterator<InputIt>::value, int> = 0> | |
| void append(cmList& v, InputIt first, InputIt last) | |
| { | |
| v.append(first, last, cmList::ExpandElements::No); | |
| } | |
| template <typename Range, | |
| cm::enable_if_t<cm::is_input_range<Range>::value, int> = 0> | |
| void append(cmList& v, Range const& r) | |
| { | |
| v.append(r.begin(), r.end(), cmList::ExpandElements::No); | |
| } | |
| #else | |
| template < | |
| typename InputIt, | |
| cm::enable_if_t< | |
| cm::is_input_iterator<InputIt>::value && | |
| std::is_convertible<typename std::iterator_traits<InputIt>::value_type, | |
| cmList::value_type>::value, | |
| int> = 0> | |
| void append(cmList& v, InputIt first, InputIt last) | |
| { | |
| v.append(first, last, cmList::ExpandElements::No); | |
| } | |
| template <typename Range, | |
| cm::enable_if_t<cm::is_input_range<Range>::value && | |
| std::is_convertible<typename Range::value_type, | |
| cmList::value_type>::value, | |
| int> = 0> | |
| void append(cmList& v, Range const& r) | |
| { | |
| v.append(r.begin(), r.end(), cmList::ExpandElements::No); | |
| } | |
| #endif | |
| } // namespace cm | |
| /** | |
| * Helper functions for legacy support. Use preferably cmList class directly | |
| * or the static methods of the class. | |
| */ | |
| inline void cmExpandList( | |
| cm::string_view arg, std::vector<std::string>& argsOut, | |
| cmList::EmptyElements emptyElements = cmList::EmptyElements::No) | |
| { | |
| cmList::append(argsOut, arg, emptyElements); | |
| } | |
| inline void cmExpandList( | |
| cmValue arg, std::vector<std::string>& argsOut, | |
| cmList::EmptyElements emptyElements = cmList::EmptyElements::No) | |
| { | |
| cmList::append(argsOut, arg, emptyElements); | |
| } |