add pipestream ctor overload for vectors of string
authorPhilipp Gesang <philipp.gesang@intra2net.com>
Tue, 2 Jan 2018 16:10:13 +0000 (17:10 +0100)
committerPhilipp Gesang <philipp.gesang@intra2net.com>
Mon, 13 Aug 2018 13:14:33 +0000 (15:14 +0200)
Add definitions that make passing a vector<string> equivalent to
passing a char**, i. e. take the execve() path.

src/pipestream.cpp
src/pipestream.hxx
test/test_pipestream.cpp

index ebcc6c2..cd9347a 100644 (file)
@@ -100,6 +100,11 @@ std::string capture_exec (const std::string &command, ExecResult &res)
 std::string capture_exec (const char *const *command, ExecResult &res)
 { return capture_exec<const char *const *>(command, res); }
 
+std::string capture_exec (const std::vector<std::string> &command, ExecResult &res)
+{
+    return capture_exec<const std::vector<std::string> &>(command, res);
+}
+
 #define PIPE_CTOR_FAIL(where) \
     do { \
         throw EXCEPTION (pipestream_error, \
@@ -197,6 +202,25 @@ inpipebuf::inpipebuf(const char *const *command)
     setg (&buffer, &buffer, &buffer);
 }
 
+inpipebuf::inpipebuf(const std::vector<std::string> &command)
+    : pipe (NULL) /* brr: shadowing global ident */
+    , status_set (NULL)
+    , exit_status (NULL)
+{
+    if (command.empty ()) {
+        PIPE_CTOR_FAIL("command");
+    }
+
+    const boost::shared_array <char *> argv = mk_argv (command);
+    if (!argv) {
+        PIPE_CTOR_FAIL("malloc");
+    }
+
+    this->pipe = this->init_without_shell (argv.get ());
+
+    setg (&buffer, &buffer, &buffer);
+}
+
 inpipebuf::inpipebuf(const std::string& command)
 {
     status_set = NULL;
index 6f83006..d13f312 100644 (file)
@@ -33,6 +33,7 @@ on this file might be covered by the GNU General Public License.
 #include <streambuf>
 #include <istream>
 #include <ostream>
+#include <vector>
 
 struct ExecResult
 {
@@ -55,6 +56,7 @@ typedef struct ExecResult ExecResult;
 
 std::string capture_exec(const std::string& command, ExecResult &rescode);
 std::string capture_exec(const char *const *command, ExecResult &rescode);
+std::string capture_exec(const std::vector<std::string>& command, ExecResult &rescode);
 
 inline std::string capture_exec (const std::string &command)
 {
@@ -68,6 +70,12 @@ inline std::string capture_exec(const char *const *command)
     return capture_exec(command,r);
 }
 
+inline std::string capture_exec(const std::vector<std::string>& command)
+{
+    ExecResult r;
+    return capture_exec(command,r);
+}
+
 /** @brief runs command and provides buffered input for it through pipe
  *
  * opens pipe to command using popen; exit status available after destruction
@@ -91,6 +99,7 @@ protected:
 public:
     inpipebuf(const std::string& command);
     inpipebuf(const char *const *command);
+    inpipebuf(const std::vector<std::string> &command);
 
     ~inpipebuf();
 
@@ -117,6 +126,10 @@ public:
             : std::istream(&buf), buf(command)
     {}
 
+    inpipestream(const std::vector<std::string> &command)
+            : std::istream(&buf), buf(command)
+    {}
+
     void store_exit_status(bool *_status_set, int *_exit_status)
     { buf.store_exit_status(_status_set, _exit_status); }
 };
index a58c89a..cf806c4 100644 (file)
@@ -27,7 +27,6 @@
 
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
-#include <boost/algorithm/string/replace.hpp>
 
 #include "stringfunc.hxx"
 #include "pipestream.hxx"
@@ -51,6 +50,19 @@ BOOST_AUTO_TEST_SUITE(pipestream)
             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
         }
 
+        BOOST_AUTO_TEST_CASE(abspath_zeros_shell_ok_result)
+        {
+            ExecResult exres;
+            const std::string result =
+                    capture_exec (I2n::join_string (zero_bytes_argv, " "),
+                                  exres);
+
+            BOOST_CHECK(exres.normal_exit);
+            BOOST_CHECK_EQUAL(exres.return_code, 0);
+            BOOST_CHECK(!exres.terminated_by_signal);
+            BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
+        }
+
         BOOST_AUTO_TEST_CASE(abspath_zeros_noshell_ok)
         {
             const std::string result = capture_exec (zero_bytes_argv);
@@ -58,6 +70,32 @@ BOOST_AUTO_TEST_SUITE(pipestream)
             BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
         }
 
+        BOOST_AUTO_TEST_CASE(abspath_zeros_noshell_ok_strvec)
+        {
+            std::vector<std::string> argvec;
+            const char *const *argp = zero_bytes_argv;
+            const char *       cur  = NULL;
+
+            while ((cur = *argp++) != NULL) {
+                argvec.push_back (std::string (cur));
+            }
+
+            const std::string result = capture_exec (argvec);
+
+            BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
+        }
+
+        BOOST_AUTO_TEST_CASE(abspath_zeros_noshell_ok_result)
+        {
+            ExecResult exres;
+            const std::string result = capture_exec (zero_bytes_argv, exres);
+
+            BOOST_CHECK(exres.normal_exit);
+            BOOST_CHECK_EQUAL(exres.return_code, 0);
+            BOOST_CHECK(!exres.terminated_by_signal);
+            BOOST_CHECK_EQUAL(result.size (), ENOUGH_ZEROS);
+        }
+
     BOOST_AUTO_TEST_SUITE_END() /* [pipestream->read] */
 
 BOOST_AUTO_TEST_SUITE_END() /* [pipestream] */