Răsfoiți Sursa

ENH: add REMOVE_DUPLICATES subcommand to LIST command (and test). Remove duplicates from a list (keep the ordering)

Sebastien Barre 18 ani în urmă
părinte
comite
f64d3d0b77
3 a modificat fișierele cu 73 adăugiri și 0 ștergeri
  1. 66 0
      Source/cmListCommand.cxx
  2. 3 0
      Source/cmListCommand.h
  3. 4 0
      Tests/CMakeTests/ListTest.cmake.in

+ 66 - 0
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);
@@ -392,6 +396,68 @@ bool cmListCommand
   return true;
 }
 
+//----------------------------------------------------------------------------
+bool cmListCommand
+::HandleRemoveDuplicatesCommand(std::vector<std::string> 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<std::string> 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<std::string> unique(varArgsExpanded.begin(), varArgsExpanded.end());
+  std::set<std::string>::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<std::string> unique;
+  std::vector<std::string>::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<std::string> const& args)

+ 3 - 0
Source/cmListCommand.h

@@ -73,6 +73,7 @@ public:
       "  list(INSERT <list> <element_index> <element> [<element> ...])\n"
       "  list(REMOVE_ITEM <list> <value> [<value> ...])\n"
       "  list(REMOVE_AT <list> <index> [<index> ...])\n"
+      "  list(REMOVE_DUPLICATES <list>)\n"
       "  list(REVERSE <list>)\n"
       "  list(SORT <list>)\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<std::string> const& args);
   bool HandleRemoveAtCommand(std::vector<std::string> const& args);
   bool HandleRemoveItemCommand(std::vector<std::string> const& args);
+  bool HandleRemoveDuplicatesCommand(std::vector<std::string> const& args);
   bool HandleSortCommand(std::vector<std::string> const& args);
   bool HandleReverseCommand(std::vector<std::string> const& args);
 

+ 4 - 0
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")