Add a GetParameterBuilder function to cvd::Command

A parameter builder object allows to add any number of components to a
single parameter, event when that number is not known at build
time (this is impossible to do with AddParameter). This is especially
useful when adding a variable number of file descriptor to a command.

Bug: 131929344
Test: run locally
Change-Id: Ib17bfed73abd217182a5d3c40015c780a27389bd
diff --git a/common/libs/utils/subprocess.cpp b/common/libs/utils/subprocess.cpp
index 773a56c..18dbbeb 100644
--- a/common/libs/utils/subprocess.cpp
+++ b/common/libs/utils/subprocess.cpp
@@ -188,6 +188,17 @@
   return retval;
 }
 
+Command::ParameterBuilder::~ParameterBuilder() {
+  Build();
+}
+void Command::ParameterBuilder::Build()  {
+  auto param = stream_.str();
+  stream_ = std::stringstream();
+  if (param.size()) {
+    cmd_->AddParameter(param);
+  }
+}
+
 Command::~Command() {
   // Close all inherited file descriptors
   for(const auto& entry: inherited_fds_) {
diff --git a/common/libs/utils/subprocess.h b/common/libs/utils/subprocess.h
index a7485c2..a299798 100644
--- a/common/libs/utils/subprocess.h
+++ b/common/libs/utils/subprocess.h
@@ -85,6 +85,24 @@
            BuildParameter(stream, args...);
   }
  public:
+  class ParameterBuilder {
+  public:
+    ParameterBuilder(Command* cmd) : cmd_(cmd) {};
+    ParameterBuilder(ParameterBuilder&& builder) = default;
+    ~ParameterBuilder();
+
+    template<typename T>
+    ParameterBuilder& operator<<(T t) {
+      cmd_->BuildParameter(&stream_, t);
+      return *this;
+    }
+
+    void Build();
+  private:
+    cvd::Command* cmd_;
+    std::stringstream stream_;
+  };
+
   Command(const std::string& executable) {
     command_.push_back(executable);
   }
@@ -117,6 +135,10 @@
     return false;
   }
 
+  ParameterBuilder GetParameterBuilder() {
+    return ParameterBuilder(this);
+  }
+
   // Redirects the standard IO of the command.
   bool RedirectStdIO(Subprocess::StdIOChannel channel, cvd::SharedFD shared_fd);