| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401 |
- /* 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 <cstdint>
- #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;
- /**
- * 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::intptr_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 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)
- : 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(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=(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=(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(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(const cmList& init,
- ExpandElements expandElements = ExpandElements::No,
- EmptyElements emptyElements = EmptyElements::No)
- {
- this->assign(init.begin(), init.end(), expandElements, emptyElements);
- }
- void assign(const cmList& 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(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(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; }
- 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(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, const cmList& values,
- ExpandElements expandElements = ExpandElements::No,
- 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::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, 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(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(const cmList& values,
- ExpandElements expandElements = ExpandElements::No,
- 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::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(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(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(const cmList& values,
- ExpandElements expandElements = ExpandElements::No,
- 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::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(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(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); }
- 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
- {
- 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 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& 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,
- const std::string& 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{};
- }
- const auto 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,
- 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 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)
- {
- 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);
- }
|