| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #include "cmConfigure.h" // IWYU pragma: keep
- #include "cmList.h"
- #include <algorithm>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <set>
- #include <stdexcept>
- #include <utility>
- #include <cm/memory>
- #include "cmsys/RegularExpression.hxx"
- #include "cmAlgorithms.h"
- #include "cmGeneratorExpression.h"
- #include "cmRange.h"
- #include "cmStringAlgorithms.h"
- #include "cmStringReplaceHelper.h"
- #include "cmSystemTools.h"
- cm::string_view cmList::element_separator{ ";" };
- cmList cmList::sublist(size_type pos, size_type length) const
- {
- if (pos >= this->Values.size()) {
- throw std::out_of_range(cmStrCat(
- "begin index: ", pos, " is out of range 0 - ", this->Values.size() - 1));
- }
- size_type count = (length == npos || pos + length > this->size())
- ? this->size()
- : pos + length;
- return this->sublist(this->begin() + pos, this->begin() + count);
- }
- cmList::size_type cmList::find(cm::string_view value) const
- {
- auto res = std::find(this->Values.begin(), this->Values.end(), value);
- if (res == this->Values.end()) {
- return npos;
- }
- return std::distance(this->Values.begin(), res);
- }
- cmList& cmList::remove_duplicates()
- {
- auto newEnd = cmRemoveDuplicates(this->Values);
- this->Values.erase(newEnd, this->Values.end());
- return *this;
- }
- namespace {
- class MatchesRegex
- {
- public:
- MatchesRegex(cmsys::RegularExpression& regex, cmList::FilterMode mode)
- : Regex(regex)
- , IncludeMatches(mode == cmList::FilterMode::INCLUDE)
- {
- }
- bool operator()(const std::string& target)
- {
- return this->Regex.find(target) ^ this->IncludeMatches;
- }
- private:
- cmsys::RegularExpression& Regex;
- const bool IncludeMatches;
- };
- }
- cmList& cmList::filter(cm::string_view pattern, FilterMode mode)
- {
- cmsys::RegularExpression regex(std::string{ pattern });
- if (!regex.is_valid()) {
- throw std::invalid_argument(
- cmStrCat("sub-command FILTER, mode REGEX failed to compile regex \"",
- pattern, "\"."));
- }
- auto it = std::remove_if(this->Values.begin(), this->Values.end(),
- MatchesRegex{ regex, mode });
- this->Values.erase(it, this->Values.end());
- return *this;
- }
- namespace {
- class StringSorter
- {
- protected:
- using StringFilter = std::function<std::string(const std::string&)>;
- using OrderMode = cmList::SortConfiguration::OrderMode;
- using CompareMethod = cmList::SortConfiguration::CompareMethod;
- using CaseSensitivity = cmList::SortConfiguration::CaseSensitivity;
- StringFilter GetCompareFilter(CompareMethod compare)
- {
- return (compare == CompareMethod::FILE_BASENAME)
- ? cmSystemTools::GetFilenameName
- : nullptr;
- }
- StringFilter GetCaseFilter(CaseSensitivity sensitivity)
- {
- return (sensitivity == CaseSensitivity::INSENSITIVE)
- ? cmSystemTools::LowerCase
- : nullptr;
- }
- using ComparisonFunction =
- std::function<bool(const std::string&, const std::string&)>;
- ComparisonFunction GetComparisonFunction(CompareMethod compare)
- {
- if (compare == CompareMethod::NATURAL) {
- return std::function<bool(const std::string&, const std::string&)>(
- [](const std::string& x, const std::string& y) {
- return cmSystemTools::strverscmp(x, y) < 0;
- });
- }
- return std::function<bool(const std::string&, const std::string&)>(
- [](const std::string& x, const std::string& y) { return x < y; });
- }
- public:
- StringSorter(cmList::SortConfiguration const& config)
- : Filters{ this->GetCompareFilter(config.Compare),
- this->GetCaseFilter(config.Case) }
- , SortMethod(this->GetComparisonFunction(config.Compare))
- , Descending(config.Order == OrderMode::DESCENDING)
- {
- }
- std::string ApplyFilter(const std::string& argument)
- {
- std::string result = argument;
- for (auto const& filter : this->Filters) {
- if (filter != nullptr) {
- result = filter(result);
- }
- }
- return result;
- }
- bool operator()(const std::string& a, const std::string& b)
- {
- std::string af = this->ApplyFilter(a);
- std::string bf = this->ApplyFilter(b);
- bool result;
- if (this->Descending) {
- result = this->SortMethod(bf, af);
- } else {
- result = this->SortMethod(af, bf);
- }
- return result;
- }
- private:
- StringFilter Filters[2] = { nullptr, nullptr };
- ComparisonFunction SortMethod;
- bool Descending;
- };
- }
- cmList::SortConfiguration::SortConfiguration() = default;
- cmList& cmList::sort(const SortConfiguration& cfg)
- {
- SortConfiguration config{ cfg };
- if (config.Order == SortConfiguration::OrderMode::DEFAULT) {
- config.Order = SortConfiguration::OrderMode::ASCENDING;
- }
- if (config.Compare == SortConfiguration::CompareMethod::DEFAULT) {
- config.Compare = SortConfiguration::CompareMethod::STRING;
- }
- if (config.Case == SortConfiguration::CaseSensitivity::DEFAULT) {
- config.Case = SortConfiguration::CaseSensitivity::SENSITIVE;
- }
- if ((config.Compare == SortConfiguration::CompareMethod::STRING) &&
- (config.Case == SortConfiguration::CaseSensitivity::SENSITIVE) &&
- (config.Order == SortConfiguration::OrderMode::ASCENDING)) {
- std::sort(this->Values.begin(), this->Values.end());
- } else {
- StringSorter sorter(config);
- std::sort(this->Values.begin(), this->Values.end(), sorter);
- }
- return *this;
- }
- namespace {
- using transform_type = std::function<std::string(const std::string&)>;
- using transform_error = cmList::transform_error;
- class TransformSelector : public cmList::TransformSelector
- {
- public:
- ~TransformSelector() override = default;
- std::string Tag;
- const std::string& GetTag() override { return this->Tag; }
- virtual bool Validate(std::size_t count = 0) = 0;
- virtual bool InSelection(const std::string&) = 0;
- virtual void Transform(cmList::container_type& list,
- const transform_type& transform)
- {
- std::transform(list.begin(), list.end(), list.begin(), transform);
- }
- protected:
- TransformSelector(std::string&& tag)
- : Tag(std::move(tag))
- {
- }
- };
- class TransformNoSelector : public TransformSelector
- {
- public:
- TransformNoSelector()
- : TransformSelector("NO SELECTOR")
- {
- }
- bool Validate(std::size_t) override { return true; }
- bool InSelection(const std::string&) override { return true; }
- };
- class TransformSelectorRegex : public TransformSelector
- {
- public:
- TransformSelectorRegex(const std::string& regex)
- : TransformSelector("REGEX")
- , Regex(regex)
- {
- }
- TransformSelectorRegex(std::string&& regex)
- : TransformSelector("REGEX")
- , Regex(regex)
- {
- }
- bool Validate(std::size_t) override { return this->Regex.is_valid(); }
- bool InSelection(const std::string& value) override
- {
- return this->Regex.find(value);
- }
- cmsys::RegularExpression Regex;
- };
- class TransformSelectorIndexes : public TransformSelector
- {
- public:
- std::vector<index_type> Indexes;
- bool InSelection(const std::string&) override { return true; }
- void Transform(std::vector<std::string>& list,
- const transform_type& transform) override
- {
- this->Validate(list.size());
- for (auto index : this->Indexes) {
- list[index] = transform(list[index]);
- }
- }
- protected:
- TransformSelectorIndexes(std::string&& tag)
- : TransformSelector(std::move(tag))
- {
- }
- TransformSelectorIndexes(std::string&& tag, std::vector<int> const& indexes)
- : TransformSelector(std::move(tag))
- , Indexes(indexes)
- {
- }
- TransformSelectorIndexes(std::string&& tag, std::vector<int>&& indexes)
- : TransformSelector(std::move(tag))
- , Indexes(indexes)
- {
- }
- int NormalizeIndex(index_type index, std::size_t count)
- {
- if (index < 0) {
- index = static_cast<index_type>(count) + index;
- }
- if (index < 0 || count <= static_cast<std::size_t>(index)) {
- throw transform_error(cmStrCat(
- "sub-command TRANSFORM, selector ", this->Tag, ", index: ", index,
- " out of range (-", count, ", ", count - 1, ")."));
- }
- return index;
- }
- };
- class TransformSelectorAt : public TransformSelectorIndexes
- {
- public:
- TransformSelectorAt(std::vector<index_type> const& indexes)
- : TransformSelectorIndexes("AT", indexes)
- {
- }
- TransformSelectorAt(std::vector<index_type>&& indexes)
- : TransformSelectorIndexes("AT", std::move(indexes))
- {
- }
- bool Validate(std::size_t count) override
- {
- decltype(this->Indexes) indexes;
- for (auto index : this->Indexes) {
- indexes.push_back(this->NormalizeIndex(index, count));
- }
- this->Indexes = std::move(indexes);
- return true;
- }
- };
- class TransformSelectorFor : public TransformSelectorIndexes
- {
- public:
- TransformSelectorFor(int start, int stop, int step)
- : TransformSelectorIndexes("FOR")
- , Start(start)
- , Stop(stop)
- , Step(step)
- {
- }
- bool Validate(std::size_t count) override
- {
- this->Start = this->NormalizeIndex(this->Start, count);
- this->Stop = this->NormalizeIndex(this->Stop, count);
- // Does stepping move us further from the end?
- if (this->Start > this->Stop) {
- throw transform_error(
- cmStrCat("sub-command TRANSFORM, selector FOR "
- "expects <start> to be no greater than <stop> (",
- this->Start, " > ", this->Stop, ")"));
- }
- // compute indexes
- auto size = (this->Stop - this->Start + 1) / this->Step;
- if ((this->Stop - this->Start + 1) % this->Step != 0) {
- size += 1;
- }
- this->Indexes.resize(size);
- auto start = this->Start;
- auto step = this->Step;
- std::generate(this->Indexes.begin(), this->Indexes.end(),
- [&start, step]() -> int {
- auto r = start;
- start += step;
- return r;
- });
- return true;
- }
- private:
- index_type Start, Stop, Step;
- };
- class TransformAction
- {
- public:
- virtual ~TransformAction() = default;
- void Initialize(TransformSelector* selector) { this->Selector = selector; }
- virtual void Initialize(TransformSelector*, const std::string&) {}
- virtual void Initialize(TransformSelector*, const std::string&,
- const std::string&)
- {
- }
- virtual void Initialize(TransformSelector* selector,
- const std::vector<std::string>&)
- {
- this->Initialize(selector);
- }
- virtual std::string operator()(const std::string& s) = 0;
- protected:
- TransformSelector* Selector;
- };
- class TransformActionAppend : public TransformAction
- {
- public:
- using TransformAction::Initialize;
- void Initialize(TransformSelector* selector,
- const std::string& append) override
- {
- TransformAction::Initialize(selector);
- this->Append = append;
- }
- void Initialize(TransformSelector* selector,
- const std::vector<std::string>& append) override
- {
- this->Initialize(selector, append.front());
- }
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- return cmStrCat(s, this->Append);
- }
- return s;
- }
- private:
- std::string Append;
- };
- class TransformActionPrepend : public TransformAction
- {
- public:
- using TransformAction::Initialize;
- void Initialize(TransformSelector* selector,
- const std::string& prepend) override
- {
- TransformAction::Initialize(selector);
- this->Prepend = prepend;
- }
- void Initialize(TransformSelector* selector,
- const std::vector<std::string>& prepend) override
- {
- this->Initialize(selector, prepend.front());
- }
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- return cmStrCat(this->Prepend, s);
- }
- return s;
- }
- private:
- std::string Prepend;
- };
- class TransformActionToUpper : public TransformAction
- {
- public:
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- return cmSystemTools::UpperCase(s);
- }
- return s;
- }
- };
- class TransformActionToLower : public TransformAction
- {
- public:
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- return cmSystemTools::LowerCase(s);
- }
- return s;
- }
- };
- class TransformActionStrip : public TransformAction
- {
- public:
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- return cmTrimWhitespace(s);
- }
- return s;
- }
- };
- class TransformActionGenexStrip : public TransformAction
- {
- public:
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- return cmGeneratorExpression::Preprocess(
- s, cmGeneratorExpression::StripAllGeneratorExpressions);
- }
- return s;
- }
- };
- class TransformActionReplace : public TransformAction
- {
- public:
- using TransformAction::Initialize;
- void Initialize(TransformSelector* selector, const std::string& regex,
- const std::string& replace) override
- {
- TransformAction::Initialize(selector);
- this->ReplaceHelper =
- cm::make_unique<cmStringReplaceHelper>(regex, replace);
- if (!this->ReplaceHelper->IsRegularExpressionValid()) {
- throw transform_error(
- cmStrCat("sub-command TRANSFORM, action REPLACE: Failed to compile "
- "regex \"",
- regex, "\"."));
- }
- if (!this->ReplaceHelper->IsReplaceExpressionValid()) {
- throw transform_error(cmStrCat("sub-command TRANSFORM, action REPLACE: ",
- this->ReplaceHelper->GetError(), "."));
- }
- }
- void Initialize(TransformSelector* selector,
- const std::vector<std::string>& args) override
- {
- this->Initialize(selector, args[0], args[1]);
- }
- std::string operator()(const std::string& s) override
- {
- if (this->Selector->InSelection(s)) {
- // Scan through the input for all matches.
- std::string output;
- if (!this->ReplaceHelper->Replace(s, output)) {
- throw transform_error(
- cmStrCat("sub-command TRANSFORM, action REPLACE: ",
- this->ReplaceHelper->GetError(), "."));
- }
- return output;
- }
- return s;
- }
- private:
- std::unique_ptr<cmStringReplaceHelper> ReplaceHelper;
- };
- // Descriptor of action
- // Arity: number of arguments required for the action
- // Transform: Object implementing the action
- struct ActionDescriptor
- {
- ActionDescriptor(cmList::TransformAction action)
- : Action(action)
- {
- }
- ActionDescriptor(cmList::TransformAction action, std::string name,
- std::size_t arity,
- std::unique_ptr<TransformAction> transform)
- : Action(action)
- , Name(std::move(name))
- , Arity(arity)
- , Transform(std::move(transform))
- {
- }
- operator cmList::TransformAction() const { return this->Action; }
- cmList::TransformAction Action;
- std::string Name;
- std::size_t Arity = 0;
- std::unique_ptr<TransformAction> Transform;
- };
- // Build a set of supported actions.
- using ActionDescriptorSet = std::set<
- ActionDescriptor,
- std::function<bool(cmList::TransformAction, cmList::TransformAction)>>;
- ActionDescriptorSet Descriptors([](cmList::TransformAction x,
- cmList::TransformAction y) {
- return x < y;
- });
- ActionDescriptorSet::iterator TransformConfigure(
- cmList::TransformAction action,
- std::unique_ptr<cmList::TransformSelector>& selector, std::size_t arity)
- {
- if (Descriptors.empty()) {
- Descriptors.emplace(cmList::TransformAction::APPEND, "APPEND", 1,
- cm::make_unique<TransformActionAppend>());
- Descriptors.emplace(cmList::TransformAction::PREPEND, "PREPEND", 1,
- cm::make_unique<TransformActionPrepend>());
- Descriptors.emplace(cmList::TransformAction::TOUPPER, "TOUPPER", 0,
- cm::make_unique<TransformActionToUpper>());
- Descriptors.emplace(cmList::TransformAction::TOLOWER, "TOLOWER", 0,
- cm::make_unique<TransformActionToLower>());
- Descriptors.emplace(cmList::TransformAction::STRIP, "STRIP", 0,
- cm::make_unique<TransformActionStrip>());
- Descriptors.emplace(cmList::TransformAction::GENEX_STRIP, "GENEX_STRIP", 0,
- cm::make_unique<TransformActionGenexStrip>());
- Descriptors.emplace(cmList::TransformAction::REPLACE, "REPLACE", 2,
- cm::make_unique<TransformActionReplace>());
- }
- auto descriptor = Descriptors.find(action);
- if (descriptor == Descriptors.end()) {
- throw transform_error(cmStrCat(" sub-command TRANSFORM, ",
- std::to_string(static_cast<int>(action)),
- " invalid action."));
- }
- if (descriptor->Arity != arity) {
- throw transform_error(cmStrCat("sub-command TRANSFORM, action ",
- descriptor->Name, " expects ",
- descriptor->Arity, " argument(s)."));
- }
- if (!selector) {
- selector = cm::make_unique<TransformNoSelector>();
- }
- return descriptor;
- }
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewAT(
- std::initializer_list<index_type> indexes)
- {
- return cm::make_unique<TransformSelectorAt>(
- std::vector<index_type>{ indexes.begin(), indexes.end() });
- ;
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewAT(
- std::vector<index_type> const& indexes)
- {
- return cm::make_unique<TransformSelectorAt>(indexes);
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewAT(
- std::vector<index_type>&& indexes)
- {
- return cm::make_unique<TransformSelectorAt>(std::move(indexes));
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewFOR(
- std::initializer_list<index_type> indexes)
- {
- if (indexes.size() < 2 || indexes.size() > 3) {
- throw transform_error("sub-command TRANSFORM, selector FOR "
- "expects 2 or 3 arguments");
- }
- if (indexes.size() == 3 && *(indexes.begin() + 2) < 0) {
- throw transform_error("sub-command TRANSFORM, selector FOR expects "
- "positive numeric value for <step>.");
- }
- return cm::make_unique<TransformSelectorFor>(
- *indexes.begin(), *(indexes.begin() + 1),
- indexes.size() == 3 ? *(indexes.begin() + 2) : 1);
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewFOR(
- std::vector<index_type> const& indexes)
- {
- if (indexes.size() < 2 || indexes.size() > 3) {
- throw transform_error("sub-command TRANSFORM, selector FOR "
- "expects 2 or 3 arguments");
- }
- if (indexes.size() == 3 && indexes[2] < 0) {
- throw transform_error("sub-command TRANSFORM, selector FOR expects "
- "positive numeric value for <step>.");
- }
- return cm::make_unique<TransformSelectorFor>(
- indexes[0], indexes[1], indexes.size() == 3 ? indexes[2] : 1);
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewFOR(
- std::vector<index_type>&& indexes)
- {
- if (indexes.size() < 2 || indexes.size() > 3) {
- throw transform_error("sub-command TRANSFORM, selector FOR "
- "expects 2 or 3 arguments");
- }
- if (indexes.size() == 3 && indexes[2] < 0) {
- throw transform_error("sub-command TRANSFORM, selector FOR expects "
- "positive numeric value for <step>.");
- }
- return cm::make_unique<TransformSelectorFor>(
- indexes[0], indexes[1], indexes.size() == 3 ? indexes[2] : 1);
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewREGEX(
- std::string const& regex)
- {
- std::unique_ptr<::TransformSelector> selector =
- cm::make_unique<TransformSelectorRegex>(regex);
- if (!selector->Validate()) {
- throw transform_error(
- cmStrCat("sub-command TRANSFORM, selector REGEX failed to compile "
- "regex \"",
- regex, "\"."));
- }
- // weird construct to please all compilers
- return std::unique_ptr<cmList::TransformSelector>(selector.release());
- }
- std::unique_ptr<cmList::TransformSelector> cmList::TransformSelector::NewREGEX(
- std::string&& regex)
- {
- std::unique_ptr<::TransformSelector> selector =
- cm::make_unique<TransformSelectorRegex>(std::move(regex));
- if (!selector->Validate()) {
- throw transform_error(
- cmStrCat("sub-command TRANSFORM, selector REGEX failed to compile "
- "regex \"",
- regex, "\"."));
- }
- // weird construct to please all compilers
- return std::unique_ptr<cmList::TransformSelector>(selector.release());
- }
- cmList& cmList::transform(TransformAction action,
- std::unique_ptr<TransformSelector> selector)
- {
- auto descriptor = TransformConfigure(action, selector, 0);
- descriptor->Transform->Initialize(
- static_cast<::TransformSelector*>(selector.get()));
- static_cast<::TransformSelector&>(*selector).Transform(
- this->Values, [&descriptor](const std::string& s) -> std::string {
- return (*descriptor->Transform)(s);
- });
- return *this;
- }
- cmList& cmList::transform(TransformAction action, std::string const& arg,
- std::unique_ptr<TransformSelector> selector)
- {
- auto descriptor = TransformConfigure(action, selector, 1);
- descriptor->Transform->Initialize(
- static_cast<::TransformSelector*>(selector.get()), arg);
- static_cast<::TransformSelector&>(*selector).Transform(
- this->Values, [&descriptor](const std::string& s) -> std::string {
- return (*descriptor->Transform)(s);
- });
- return *this;
- }
- cmList& cmList::transform(TransformAction action, std::string const& arg1,
- std::string const& arg2,
- std::unique_ptr<TransformSelector> selector)
- {
- auto descriptor = TransformConfigure(action, selector, 2);
- descriptor->Transform->Initialize(
- static_cast<::TransformSelector*>(selector.get()), arg1, arg2);
- static_cast<::TransformSelector&>(*selector).Transform(
- this->Values, [&descriptor](const std::string& s) -> std::string {
- return (*descriptor->Transform)(s);
- });
- return *this;
- }
- cmList& cmList::transform(TransformAction action,
- std::vector<std::string> const& args,
- std::unique_ptr<TransformSelector> selector)
- {
- auto descriptor = TransformConfigure(action, selector, args.size());
- descriptor->Transform->Initialize(
- static_cast<::TransformSelector*>(selector.get()), args);
- static_cast<::TransformSelector&>(*selector).Transform(
- this->Values, [&descriptor](const std::string& s) -> std::string {
- return (*descriptor->Transform)(s);
- });
- return *this;
- }
- std::string cmList::join(cm::string_view glue) const
- {
- return cmJoin(this->Values, glue);
- }
- std::string& cmList::append(cm::string_view value, std::string& list)
- {
- if (list.empty()) {
- list = std::string(value);
- } else {
- list += cmStrCat(cmList::element_separator, value);
- }
- return list;
- }
- std::string& cmList::prepend(cm::string_view value, std::string& list)
- {
- if (list.empty()) {
- list = std::string(value);
- } else {
- list.insert(0, cmStrCat(value, cmList::element_separator));
- }
- return list;
- }
- cmList::size_type cmList::ComputeIndex(index_type pos, bool boundCheck) const
- {
- if (boundCheck) {
- if (this->Values.empty()) {
- throw std::out_of_range(
- cmStrCat("index: ", pos, " out of range (0, 0)"));
- }
- if (!this->Values.empty()) {
- auto length = this->Values.size();
- if (pos < 0) {
- pos = static_cast<index_type>(length) + pos;
- }
- if (pos < 0 || length <= static_cast<size_type>(pos)) {
- throw std::out_of_range(cmStrCat("index: ", pos, " out of range (-",
- this->Values.size(), ", ",
- this->Values.size() - 1, ")"));
- }
- }
- return pos;
- }
- return pos < 0 ? this->Values.size() + pos : pos;
- }
- cmList::size_type cmList::ComputeInsertIndex(index_type pos,
- bool boundCheck) const
- {
- if (boundCheck) {
- if (this->Values.empty() && pos != 0) {
- throw std::out_of_range(
- cmStrCat("index: ", pos, " out of range (0, 0)"));
- }
- if (!this->Values.empty()) {
- auto length = this->Values.size();
- if (pos < 0) {
- pos = static_cast<index_type>(length) + pos;
- }
- if (pos < 0 || length < static_cast<size_type>(pos)) {
- throw std::out_of_range(cmStrCat("index: ", pos, " out of range (-",
- this->Values.size(), ", ",
- this->Values.size(), ")"));
- }
- }
- return pos;
- }
- return pos < 0 ? this->Values.size() + pos : pos;
- }
- cmList cmList::GetItems(std::vector<index_type>&& indexes) const
- {
- cmList listItems;
- for (auto index : indexes) {
- listItems.emplace_back(this->at(index));
- }
- return listItems;
- }
- cmList& cmList::RemoveItems(std::vector<index_type>&& indexes)
- {
- if (indexes.empty()) {
- return *this;
- }
- // compute all indexes
- std::vector<size_type> idx(indexes.size());
- std::transform(
- indexes.cbegin(), indexes.cend(), idx.begin(),
- [this](const index_type& index) { return this->ComputeIndex(index); });
- std::sort(idx.begin(), idx.end(),
- [](size_type l, size_type r) { return l > r; });
- auto newEnd = std::unique(idx.begin(), idx.end());
- idx.erase(newEnd, idx.end());
- for (auto index : idx) {
- this->erase(this->begin() + index);
- }
- return *this;
- }
- cmList& cmList::RemoveItems(std::vector<std::string>&& items)
- {
- std::sort(items.begin(), items.end());
- auto last = std::unique(items.begin(), items.end());
- auto first = items.begin();
- auto newEnd = cmRemoveMatching(this->Values, cmMakeRange(first, last));
- this->Values.erase(newEnd, this->Values.end());
- return *this;
- }
- cmList::container_type::iterator cmList::Insert(
- container_type::const_iterator pos, std::string&& value,
- container_type& container, ExpandElements expandElements,
- EmptyElements emptyElements)
- {
- auto delta = std::distance(container.cbegin(), pos);
- auto insertPos = container.begin() + delta;
- if (expandElements == ExpandElements::Yes) {
- // If argument is empty, it is an empty list.
- if (emptyElements == EmptyElements::No && value.empty()) {
- return insertPos;
- }
- // if there are no ; in the name then just copy the current string
- if (value.find(';') == std::string::npos) {
- return container.insert(insertPos, std::move(value));
- }
- std::string newValue;
- // Break the string at non-escaped semicolons not nested in [].
- int squareNesting = 0;
- auto last = value.begin();
- auto const cend = value.end();
- for (auto c = last; c != cend; ++c) {
- switch (*c) {
- case '\\': {
- // We only want to allow escaping of semicolons. Other
- // escapes should not be processed here.
- auto cnext = c + 1;
- if ((cnext != cend) && *cnext == ';') {
- newValue.append(last, c);
- // Skip over the escape character
- last = cnext;
- c = cnext;
- }
- } break;
- case '[': {
- ++squareNesting;
- } break;
- case ']': {
- --squareNesting;
- } break;
- case ';': {
- // brackets.
- if (squareNesting == 0) {
- newValue.append(last, c);
- // Skip over the semicolon
- last = c + 1;
- if (!newValue.empty() || emptyElements == EmptyElements::Yes) {
- // Add the last argument.
- insertPos = container.insert(insertPos, newValue);
- insertPos++;
- newValue.clear();
- }
- }
- } break;
- default: {
- // Just append this character.
- } break;
- }
- }
- newValue.append(last, cend);
- if (!newValue.empty() || emptyElements == EmptyElements::Yes) {
- // Add the last argument.
- container.insert(insertPos, std::move(newValue));
- }
- } else if (!value.empty() || emptyElements == EmptyElements::Yes) {
- return container.insert(insertPos, std::move(value));
- }
- return container.begin() + delta;
- }
|