From f64d3d0b77bfa41d64cf86e1b60e499eba7a813c Mon Sep 17 00:00:00 2001 From: Sebastien Barre Date: Wed, 12 Mar 2008 17:02:10 -0400 Subject: ENH: add REMOVE_DUPLICATES subcommand to LIST command (and test). Remove duplicates from a list (keep the ordering) --- Source/cmListCommand.cxx | 66 ++++++++++++++++++++++++++++++++++++++ Source/cmListCommand.h | 3 ++ Tests/CMakeTests/ListTest.cmake.in | 4 +++ 3 files changed, 73 insertions(+) diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index f990ad5..2b7e3f4 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -59,6 +59,10 @@ bool cmListCommand { return this->HandleRemoveItemCommand(args); } + if(subCommand == "REMOVE_DUPLICATES") + { + return this->HandleRemoveDuplicatesCommand(args); + } if(subCommand == "SORT") { return this->HandleSortCommand(args); @@ -394,6 +398,68 @@ bool cmListCommand //---------------------------------------------------------------------------- bool cmListCommand +::HandleRemoveDuplicatesCommand(std::vector const& args) +{ + if(args.size() < 2) + { + this->SetError("sub-command REMOVE_DUPLICATES requires a list as an argument."); + return false; + } + + const std::string& listName = args[1]; + // expand the variable + std::vector varArgsExpanded; + if ( !this->GetList(varArgsExpanded, listName.c_str()) ) + { + this->SetError("sub-command REMOVE_DUPLICATES requires list to be present."); + return false; + } + + std::string value; + +#if 0 + // Fast version, but does not keep the ordering + + std::set unique(varArgsExpanded.begin(), varArgsExpanded.end()); + std::set::iterator it; + for ( it = unique.begin(); it != unique.end(); ++ it ) + { + if (value.size()) + { + value += ";"; + } + value += it->c_str(); + } + +#else + + // Slower version, keep the ordering + + std::set unique; + std::vector::iterator it; + for ( it = varArgsExpanded.begin(); it != varArgsExpanded.end(); ++ it ) + { + if (unique.find(*it) != unique.end()) + { + continue; + } + unique.insert(*it); + + if (value.size()) + { + value += ";"; + } + value += it->c_str(); + } +#endif + + + this->Makefile->AddDefinition(listName.c_str(), value.c_str()); + return true; +} + +//---------------------------------------------------------------------------- +bool cmListCommand ::HandleSortCommand(std::vector const& args) { if(args.size() < 2) diff --git a/Source/cmListCommand.h b/Source/cmListCommand.h index d607b42..2e4538b 100644 --- a/Source/cmListCommand.h +++ b/Source/cmListCommand.h @@ -73,6 +73,7 @@ public: " list(INSERT [ ...])\n" " list(REMOVE_ITEM [ ...])\n" " list(REMOVE_AT [ ...])\n" + " list(REMOVE_DUPLICATES )\n" " list(REVERSE )\n" " list(SORT )\n" "LENGTH will return a given list's length.\n" @@ -84,6 +85,7 @@ public: "REMOVE_AT and REMOVE_ITEM will remove items from the list. The " "difference is that REMOVE_ITEM will remove the given items, while " "REMOVE_AT will remove the items at the given indices.\n" + "REMOVE_DUPLICATES will remove duplicated items in the list.\n" "REVERSE reverses the contents of the list in-place.\n" "SORT sorts the list in-place alphabetically.\n" "NOTES: A list in cmake is a ; separated group of strings. " @@ -110,6 +112,7 @@ protected: bool HandleInsertCommand(std::vector const& args); bool HandleRemoveAtCommand(std::vector const& args); bool HandleRemoveItemCommand(std::vector const& args); + bool HandleRemoveDuplicatesCommand(std::vector const& args); bool HandleSortCommand(std::vector const& args); bool HandleReverseCommand(std::vector const& args); diff --git a/Tests/CMakeTests/ListTest.cmake.in b/Tests/CMakeTests/ListTest.cmake.in index eea0da0..cf6f91a 100644 --- a/Tests/CMakeTests/ListTest.cmake.in +++ b/Tests/CMakeTests/ListTest.cmake.in @@ -82,3 +82,7 @@ TEST("SORT result" "andy;bill;brad;ken") SET(result andy bill brad ken) LIST(REVERSE result) TEST("REVERSE result" "ken;brad;bill;andy") + +SET(result bill andy bill brad ken ken ken) +LIST(REMOVE_DUPLICATES result) +TEST("REMOVE_DUPLICATES result" "bill;andy;brad;ken") -- cgit v0.12