summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2023-06-15 13:27:37 (GMT)
committerKitware Robot <kwrobot@kitware.com>2023-06-15 13:27:42 (GMT)
commita84c99694745b57cd570c33ea46d68b0a917aace (patch)
tree70b3986cc3b1efc39501becb1f2d3b7a7a0b78e2
parent0b62dede642dcb4b961b2459a2cb2480c5fc432a (diff)
parentb65d54e87694efb4962cd37348aec0ba598e5d4e (diff)
downloadCMake-a84c99694745b57cd570c33ea46d68b0a917aace.zip
CMake-a84c99694745b57cd570c33ea46d68b0a917aace.tar.gz
CMake-a84c99694745b57cd570c33ea46d68b0a917aace.tar.bz2
Merge topic 'cmuvprocesschain-external-stream-fd'
b65d54e876 cmUVStreambuf: Update URL for example code 0878306386 cmUVStream: Add cmUVStreamRead() function b8fd273ed7 cmUVProcessChain: Return output and error streams as file descriptors ec81d40be4 cmUVPipeIStream: Add cmUVPipeIStream 3b6c5efc08 cm::append: Add support for std::basic_string on SPARC/SunPro Acked-by: Kitware Robot <kwrobot@kitware.com> Tested-by: buildbot <buildbot@kitware.com> Merge-request: !8559
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx4
-rw-r--r--Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx12
-rw-r--r--Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx4
-rw-r--r--Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx4
-rw-r--r--Source/cmLDConfigLDConfigTool.cxx4
-rw-r--r--Source/cmUVProcessChain.cxx60
-rw-r--r--Source/cmUVProcessChain.h5
-rw-r--r--Source/cmUVStream.h140
-rw-r--r--Source/cmUVStreambuf.h3
-rw-r--r--Source/cmcmd.cxx13
-rw-r--r--Tests/CMakeLib/testUVProcessChain.cxx51
-rw-r--r--Tests/CMakeLib/testUVStreambuf.cxx97
-rw-r--r--Utilities/std/cmext/algorithm9
14 files changed, 315 insertions, 92 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index b01e1e7..a79366e 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -438,6 +438,7 @@ add_library(
cmUVHandlePtr.h
cmUVProcessChain.cxx
cmUVProcessChain.h
+ cmUVStream.h
cmUVStreambuf.h
cmUVSignalHackRAII.h
cmVariableWatch.cxx
diff --git a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
index c5c41e0..8043f82 100644
--- a/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
+++ b/Source/cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool.cxx
@@ -10,6 +10,7 @@
#include "cmRuntimeDependencyArchive.h"
#include "cmSystemTools.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::
cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool(
@@ -46,7 +47,8 @@ bool cmBinUtilsLinuxELFObjdumpGetRuntimeDependenciesTool::GetFileInfo(
static const cmsys::RegularExpression neededRegex("^ *NEEDED *([^\n]*)$");
static const cmsys::RegularExpression rpathRegex("^ *RPATH *([^\n]*)$");
static const cmsys::RegularExpression runpathRegex("^ *RUNPATH *([^\n]*)$");
- while (std::getline(*process.OutputStream(), line)) {
+ cmUVPipeIStream output(process.GetLoop(), process.OutputStream());
+ while (std::getline(output, line)) {
cmsys::RegularExpressionMatch match;
if (neededRegex.find(line.c_str(), match)) {
needed.push_back(match.match(1));
diff --git a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
index cf4a8fe..4c35841 100644
--- a/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
+++ b/Source/cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool.cxx
@@ -9,6 +9,7 @@
#include "cmRuntimeDependencyArchive.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::
cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool(
@@ -49,11 +50,12 @@ bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
"^ *path (.*) \\(offset [0-9]+\\)$");
static const cmsys::RegularExpression nameRegex(
"^ *name (.*) \\(offset [0-9]+\\)$");
- while (std::getline(*process.OutputStream(), line)) {
+ cmUVPipeIStream output(process.GetLoop(), process.OutputStream());
+ while (std::getline(output, line)) {
cmsys::RegularExpressionMatch cmdMatch;
if (rpathRegex.find(line.c_str(), cmdMatch)) {
- if (!std::getline(*process.OutputStream(), line) ||
- !std::getline(*process.OutputStream(), line)) {
+ // NOLINTNEXTLINE(misc-redundant-expression)
+ if (!std::getline(output, line) || !std::getline(output, line)) {
this->SetError("Invalid output from otool");
return false;
}
@@ -66,8 +68,8 @@ bool cmBinUtilsMacOSMachOOToolGetRuntimeDependenciesTool::GetFileInfo(
return false;
}
} else if (loadDylibRegex.find(line.c_str(), cmdMatch)) {
- if (!std::getline(*process.OutputStream(), line) ||
- !std::getline(*process.OutputStream(), line)) {
+ // NOLINTNEXTLINE(misc-redundant-expression)
+ if (!std::getline(output, line) || !std::getline(output, line)) {
this->SetError("Invalid output from otool");
return false;
}
diff --git a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
index 3b02c2e..cd21140 100644
--- a/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
+++ b/Source/cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool.cxx
@@ -9,6 +9,7 @@
#include "cmRuntimeDependencyArchive.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::
cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool(
@@ -43,7 +44,8 @@ bool cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool::GetFileInfo(
std::string line;
static const cmsys::RegularExpression regex(
"^ ([^\n]*\\.[Dd][Ll][Ll])\r$");
- while (std::getline(*process.OutputStream(), line)) {
+ cmUVPipeIStream output(process.GetLoop(), process.OutputStream());
+ while (std::getline(output, line)) {
cmsys::RegularExpressionMatch match;
if (regex.find(line.c_str(), match)) {
needed.push_back(match.match(1));
diff --git a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
index 2139b4b..d95da95 100644
--- a/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
+++ b/Source/cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool.cxx
@@ -10,6 +10,7 @@
#include "cmRuntimeDependencyArchive.h"
#include "cmSystemTools.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::
cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool(
@@ -44,7 +45,8 @@ bool cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool::GetFileInfo(
std::string line;
static const cmsys::RegularExpression regex(
"^\t*DLL Name: ([^\n]*\\.[Dd][Ll][Ll])$");
- while (cmSystemTools::GetLineFromStream(*process.OutputStream(), line)) {
+ cmUVPipeIStream output(process.GetLoop(), process.OutputStream());
+ while (cmSystemTools::GetLineFromStream(output, line)) {
cmsys::RegularExpressionMatch match;
if (regex.find(line.c_str(), match)) {
needed.push_back(match.match(1));
diff --git a/Source/cmLDConfigLDConfigTool.cxx b/Source/cmLDConfigLDConfigTool.cxx
index 7ce1a59..154aa27 100644
--- a/Source/cmLDConfigLDConfigTool.cxx
+++ b/Source/cmLDConfigLDConfigTool.cxx
@@ -14,6 +14,7 @@
#include "cmRuntimeDependencyArchive.h"
#include "cmSystemTools.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
cmLDConfigLDConfigTool::cmLDConfigLDConfigTool(
cmRuntimeDependencyArchive* archive)
@@ -50,7 +51,8 @@ bool cmLDConfigLDConfigTool::GetLDConfigPaths(std::vector<std::string>& paths)
std::string line;
static const cmsys::RegularExpression regex("^([^\t:]*):");
- while (std::getline(*process.OutputStream(), line)) {
+ cmUVPipeIStream output(process.GetLoop(), process.OutputStream());
+ while (std::getline(output, line)) {
cmsys::RegularExpressionMatch match;
if (regex.find(line.c_str(), match)) {
paths.push_back(match.match(1));
diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx
index cf4475b..3de7ae5 100644
--- a/Source/cmUVProcessChain.cxx
+++ b/Source/cmUVProcessChain.cxx
@@ -17,36 +17,15 @@
#include "cmGetPipes.h"
#include "cmUVHandlePtr.h"
-#include "cmUVStreambuf.h"
struct cmUVProcessChain::InternalData
{
- struct BasicStreamData
+ struct StreamData
{
- cmUVStreambuf Streambuf;
- cm::uv_pipe_ptr BuiltinStream;
+ int BuiltinStream = -1;
uv_stdio_container_t Stdio;
};
- template <typename IOStream>
- struct StreamData : public BasicStreamData
- {
- StreamData()
- : BuiltinIOStream(&this->Streambuf)
- {
- }
-
- IOStream BuiltinIOStream;
-
- IOStream* GetBuiltinStream()
- {
- if (this->BuiltinStream.get()) {
- return &this->BuiltinIOStream;
- }
- return nullptr;
- }
- };
-
struct ProcessData
{
cmUVProcessChain::InternalData* Data;
@@ -64,9 +43,9 @@ struct cmUVProcessChain::InternalData
cm::uv_loop_ptr Loop;
- StreamData<std::ostream> InputStreamData;
- StreamData<std::istream> OutputStreamData;
- StreamData<std::istream> ErrorStreamData;
+ StreamData InputStreamData;
+ StreamData OutputStreamData;
+ StreamData ErrorStreamData;
cm::uv_pipe_ptr TempOutputPipe;
cm::uv_pipe_ptr TempErrorPipe;
@@ -215,12 +194,7 @@ bool cmUVProcessChain::InternalData::Prepare(
return false;
}
- if (errorData.BuiltinStream.init(*this->Loop, 0) < 0) {
- return false;
- }
- if (uv_pipe_open(errorData.BuiltinStream, pipeFd[0]) < 0) {
- return false;
- }
+ errorData.BuiltinStream = pipeFd[0];
errorData.Stdio.flags = UV_INHERIT_FD;
errorData.Stdio.data.fd = pipeFd[1];
@@ -231,7 +205,6 @@ bool cmUVProcessChain::InternalData::Prepare(
return false;
}
- errorData.Streambuf.open(errorData.BuiltinStream);
break;
}
@@ -251,6 +224,7 @@ bool cmUVProcessChain::InternalData::Prepare(
case cmUVProcessChainBuilder::Builtin:
if (this->Builder->MergedBuiltinStreams) {
+ outputData.BuiltinStream = errorData.BuiltinStream;
outputData.Stdio.flags = UV_INHERIT_FD;
outputData.Stdio.data.fd = errorData.Stdio.data.fd;
} else {
@@ -259,12 +233,7 @@ bool cmUVProcessChain::InternalData::Prepare(
return false;
}
- if (outputData.BuiltinStream.init(*this->Loop, 0) < 0) {
- return false;
- }
- if (uv_pipe_open(outputData.BuiltinStream, pipeFd[0]) < 0) {
- return false;
- }
+ outputData.BuiltinStream = pipeFd[0];
outputData.Stdio.flags = UV_INHERIT_FD;
outputData.Stdio.data.fd = pipeFd[1];
@@ -274,8 +243,6 @@ bool cmUVProcessChain::InternalData::Prepare(
if (uv_pipe_open(this->TempOutputPipe, outputData.Stdio.data.fd) < 0) {
return false;
}
-
- outputData.Streambuf.open(outputData.BuiltinStream);
}
break;
@@ -411,17 +378,14 @@ uv_loop_t& cmUVProcessChain::GetLoop()
return *this->Data->Loop;
}
-std::istream* cmUVProcessChain::OutputStream()
+int cmUVProcessChain::OutputStream()
{
- if (this->Data->Builder->MergedBuiltinStreams) {
- return this->Data->ErrorStreamData.GetBuiltinStream();
- }
- return this->Data->OutputStreamData.GetBuiltinStream();
+ return this->Data->OutputStreamData.BuiltinStream;
}
-std::istream* cmUVProcessChain::ErrorStream()
+int cmUVProcessChain::ErrorStream()
{
- return this->Data->ErrorStreamData.GetBuiltinStream();
+ return this->Data->ErrorStreamData.BuiltinStream;
}
bool cmUVProcessChain::Valid() const
diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h
index 547a944..d7a4a0e 100644
--- a/Source/cmUVProcessChain.h
+++ b/Source/cmUVProcessChain.h
@@ -5,7 +5,6 @@
#include <array>
#include <cstddef> // IWYU pragma: keep
#include <cstdint>
-#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
@@ -99,8 +98,8 @@ public:
uv_loop_t& GetLoop();
// FIXME: Add stdin support
- std::istream* OutputStream();
- std::istream* ErrorStream();
+ int OutputStream();
+ int ErrorStream();
bool Valid() const;
bool Wait(int64_t milliseconds = -1);
diff --git a/Source/cmUVStream.h b/Source/cmUVStream.h
new file mode 100644
index 0000000..5998256
--- /dev/null
+++ b/Source/cmUVStream.h
@@ -0,0 +1,140 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <cassert>
+#include <istream>
+
+#include <cm3p/uv.h>
+
+#include "cmUVHandlePtr.h"
+#include "cmUVStreambuf.h"
+
+template <typename CharT, typename Traits = std::char_traits<CharT>>
+class cmBasicUVIStream : public std::basic_istream<CharT>
+{
+public:
+ cmBasicUVIStream();
+ cmBasicUVIStream(uv_stream_t* stream);
+
+ bool is_open() const;
+
+ void open(uv_stream_t* stream);
+
+ void close();
+
+private:
+ cmBasicUVStreambuf<CharT, Traits> Buffer;
+};
+
+template <typename CharT, typename Traits>
+cmBasicUVIStream<CharT, Traits>::cmBasicUVIStream()
+ : std::basic_istream<CharT, Traits>(&this->Buffer)
+{
+}
+
+template <typename CharT, typename Traits>
+cmBasicUVIStream<CharT, Traits>::cmBasicUVIStream(uv_stream_t* stream)
+ : cmBasicUVIStream()
+{
+ this->open(stream);
+}
+
+template <typename CharT, typename Traits>
+bool cmBasicUVIStream<CharT, Traits>::is_open() const
+{
+ return this->Buffer.is_open();
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVIStream<CharT, Traits>::open(uv_stream_t* stream)
+{
+ this->Buffer.open(stream);
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVIStream<CharT, Traits>::close()
+{
+ this->Buffer.close();
+}
+
+using cmUVIStream = cmBasicUVIStream<char>;
+
+template <typename CharT, typename Traits = std::char_traits<CharT>>
+class cmBasicUVPipeIStream : public cmBasicUVIStream<CharT, Traits>
+{
+public:
+ cmBasicUVPipeIStream();
+ cmBasicUVPipeIStream(uv_loop_t& loop, int fd);
+
+ using cmBasicUVIStream<CharT, Traits>::is_open;
+
+ void open(uv_loop_t& loop, int fd);
+
+ void close();
+
+private:
+ cm::uv_pipe_ptr Pipe;
+};
+
+template <typename CharT, typename Traits>
+cmBasicUVPipeIStream<CharT, Traits>::cmBasicUVPipeIStream() = default;
+
+template <typename CharT, typename Traits>
+cmBasicUVPipeIStream<CharT, Traits>::cmBasicUVPipeIStream(uv_loop_t& loop,
+ int fd)
+{
+ this->open(loop, fd);
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVPipeIStream<CharT, Traits>::open(uv_loop_t& loop, int fd)
+{
+ this->Pipe.init(loop, 0);
+ uv_pipe_open(this->Pipe, fd);
+ this->cmBasicUVIStream<CharT, Traits>::open(this->Pipe);
+}
+
+template <typename CharT, typename Traits>
+void cmBasicUVPipeIStream<CharT, Traits>::close()
+{
+ this->cmBasicUVIStream<CharT, Traits>::close();
+ this->Pipe.reset();
+}
+
+using cmUVPipeIStream = cmBasicUVPipeIStream<char>;
+
+template <typename ReadCallback, typename FinishCallback>
+void cmUVStreamRead(uv_stream_t* stream, ReadCallback onRead,
+ FinishCallback onFinish)
+{
+ struct ReadData
+ {
+ std::vector<char> Buffer;
+ ReadCallback OnRead;
+ FinishCallback OnFinish;
+ };
+
+ stream->data = new ReadData{ {}, std::move(onRead), std::move(onFinish) };
+ uv_read_start(
+ stream,
+ [](uv_handle_t* s, std::size_t suggestedSize, uv_buf_t* buffer) {
+ auto* data = static_cast<ReadData*>(s->data);
+ data->Buffer.resize(suggestedSize);
+ buffer->base = data->Buffer.data();
+ buffer->len = suggestedSize;
+ },
+ [](uv_stream_t* s, ssize_t nread, const uv_buf_t* buffer) {
+ auto* data = static_cast<ReadData*>(s->data);
+ if (nread > 0) {
+ (void)buffer;
+ assert(buffer->base == data->Buffer.data());
+ data->Buffer.resize(nread);
+ data->OnRead(std::move(data->Buffer));
+ } else if (nread < 0 /*|| nread == UV_EOF*/) {
+ data->OnFinish();
+ uv_read_stop(s);
+ delete data;
+ }
+ });
+}
diff --git a/Source/cmUVStreambuf.h b/Source/cmUVStreambuf.h
index efe45de..4f7b209 100644
--- a/Source/cmUVStreambuf.h
+++ b/Source/cmUVStreambuf.h
@@ -14,7 +14,8 @@
/*
* This file is based on example code from:
*
- * http://www.voidcn.com/article/p-vjnlygmc-gy.html
+ * https://web.archive.org/web/20170515211805/
+ * http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
*
* The example code was distributed under the following license:
*
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 1bbd0ac..eb1f93d 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -28,6 +28,7 @@
#include "cmSystemTools.h"
#include "cmTransformDepfile.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
#include "cmUtils.hxx"
#include "cmValue.h"
#include "cmVersion.h"
@@ -2017,10 +2018,8 @@ int cmcmd::RunPreprocessor(const std::vector<std::string>& command,
return 1;
}
if (process.GetStatus(0).ExitStatus != 0) {
- auto* errorStream = process.ErrorStream();
- if (errorStream) {
- std::cerr << errorStream->rdbuf();
- }
+ cmUVPipeIStream errorStream(process.GetLoop(), process.ErrorStream());
+ std::cerr << errorStream.rdbuf();
return 1;
}
@@ -2144,10 +2143,8 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
return result;
}
if (process.GetStatus(0).ExitStatus != 0) {
- auto* errorStream = process.ErrorStream();
- if (errorStream) {
- std::cerr << errorStream->rdbuf();
- }
+ cmUVPipeIStream errorStream(process.GetLoop(), process.ErrorStream());
+ std::cerr << errorStream.rdbuf();
return 1;
}
diff --git a/Tests/CMakeLib/testUVProcessChain.cxx b/Tests/CMakeLib/testUVProcessChain.cxx
index f3024dc..7630aa0 100644
--- a/Tests/CMakeLib/testUVProcessChain.cxx
+++ b/Tests/CMakeLib/testUVProcessChain.cxx
@@ -17,6 +17,7 @@
#include "cmStringAlgorithms.h"
#include "cmUVHandlePtr.h"
#include "cmUVProcessChain.h"
+#include "cmUVStream.h"
#include "cmUVStreambuf.h"
struct ExpectedStatus
@@ -301,16 +302,19 @@ bool testUVProcessChainBuiltin(const char* helperCommand)
return false;
}
- if (!chain->OutputStream()) {
- std::cout << "OutputStream() was null, expecting not null" << std::endl;
+ if (chain->OutputStream() < 0) {
+ std::cout << "OutputStream() was invalid, expecting valid" << std::endl;
return false;
}
- if (!chain->ErrorStream()) {
- std::cout << "ErrorStream() was null, expecting not null" << std::endl;
+ if (chain->ErrorStream() < 0) {
+ std::cout << "ErrorStream() was invalid, expecting valid" << std::endl;
return false;
}
- if (!checkOutput(*chain->OutputStream(), *chain->ErrorStream())) {
+ cmUVPipeIStream output(chain->GetLoop(), chain->OutputStream());
+ cmUVPipeIStream error(chain->GetLoop(), chain->ErrorStream());
+
+ if (!checkOutput(output, error)) {
return false;
}
@@ -330,12 +334,12 @@ bool testUVProcessChainBuiltinMerged(const char* helperCommand)
return false;
}
- if (!chain->OutputStream()) {
- std::cout << "OutputStream() was null, expecting not null" << std::endl;
+ if (chain->OutputStream() < 0) {
+ std::cout << "OutputStream() was invalid, expecting valid" << std::endl;
return false;
}
- if (!chain->ErrorStream()) {
- std::cout << "ErrorStream() was null, expecting not null" << std::endl;
+ if (chain->ErrorStream() < 0) {
+ std::cout << "ErrorStream() was invalid, expecting valid" << std::endl;
return false;
}
if (chain->OutputStream() != chain->ErrorStream()) {
@@ -344,7 +348,9 @@ bool testUVProcessChainBuiltinMerged(const char* helperCommand)
return false;
}
- std::string merged = getInput(*chain->OutputStream());
+ cmUVPipeIStream mergedStream(chain->GetLoop(), chain->OutputStream());
+
+ std::string merged = getInput(mergedStream);
auto qemuErrorPos = merged.find("qemu:");
if (qemuErrorPos != std::string::npos) {
merged.resize(qemuErrorPos);
@@ -398,12 +404,12 @@ bool testUVProcessChainExternal(const char* helperCommand)
return false;
}
- if (chain->OutputStream()) {
- std::cout << "OutputStream() was not null, expecting null" << std::endl;
+ if (chain->OutputStream() >= 0) {
+ std::cout << "OutputStream() was valid, expecting invalid" << std::endl;
return false;
}
- if (chain->ErrorStream()) {
- std::cout << "ErrorStream() was not null, expecting null" << std::endl;
+ if (chain->ErrorStream() >= 0) {
+ std::cout << "ErrorStream() was valid, expecting invalid" << std::endl;
return false;
}
@@ -446,12 +452,12 @@ bool testUVProcessChainNone(const char* helperCommand)
return false;
}
- if (chain->OutputStream()) {
- std::cout << "OutputStream() was not null, expecting null" << std::endl;
+ if (chain->OutputStream() >= 0) {
+ std::cout << "OutputStream() was valid, expecting invalid" << std::endl;
return false;
}
- if (chain->ErrorStream()) {
- std::cout << "ErrorStream() was not null, expecting null" << std::endl;
+ if (chain->ErrorStream() >= 0) {
+ std::cout << "ErrorStream() was valid, expecting invalid" << std::endl;
return false;
}
@@ -473,7 +479,8 @@ bool testUVProcessChainCwdUnchanged(const char* helperCommand)
return false;
}
- auto cwd = getInput(*chain.OutputStream());
+ cmUVPipeIStream output(chain.GetLoop(), chain.OutputStream());
+ auto cwd = getInput(output);
if (!cmHasLiteralSuffix(cwd, "/Tests/CMakeLib")) {
std::cout << "Working directory was \"" << cwd
<< "\", expected to end in \"/Tests/CMakeLib\"" << std::endl;
@@ -499,7 +506,8 @@ bool testUVProcessChainCwdChanged(const char* helperCommand)
return false;
}
- auto cwd = getInput(*chain.OutputStream());
+ cmUVPipeIStream output(chain.GetLoop(), chain.OutputStream());
+ auto cwd = getInput(output);
if (!cmHasLiteralSuffix(cwd, "/Tests")) {
std::cout << "Working directory was \"" << cwd
<< "\", expected to end in \"/Tests\"" << std::endl;
@@ -633,7 +641,8 @@ bool testUVProcessChainInputFile(const char* helperCommand)
return false;
}
- std::string output = getInput(*chain.OutputStream());
+ cmUVPipeIStream stream(chain.GetLoop(), chain.OutputStream());
+ std::string output = getInput(stream);
if (output != "HELO WRD!") {
std::cout << "Output was \"" << output << "\", expected \"HELO WRD!\""
<< std::endl;
diff --git a/Tests/CMakeLib/testUVStreambuf.cxx b/Tests/CMakeLib/testUVStreambuf.cxx
index f9ed6af..f3977d4 100644
--- a/Tests/CMakeLib/testUVStreambuf.cxx
+++ b/Tests/CMakeLib/testUVStreambuf.cxx
@@ -3,11 +3,14 @@
#include <string>
#include <vector>
+#include <cmext/algorithm>
+
#include <cm3p/uv.h>
#include <stdint.h>
#include "cmGetPipes.h"
#include "cmUVHandlePtr.h"
+#include "cmUVStream.h"
#include "cmUVStreambuf.h"
#define TEST_STR_LINE_1 "This string must be exactly 128 characters long so"
@@ -437,6 +440,90 @@ end:
return success;
}
+bool testUVPipeIStream()
+{
+ int pipe[] = { -1, -1 };
+ if (cmGetPipes(pipe) < 0) {
+ std::cout << "cmGetPipes() returned an error" << std::endl;
+ return false;
+ }
+
+ cm::uv_loop_ptr loop;
+ loop.init();
+ cm::uv_pipe_ptr pipeSink;
+ pipeSink.init(*loop, 0);
+ uv_pipe_open(pipeSink, pipe[1]);
+
+ std::string str = "Hello world!\n";
+ uv_write_t writeReq;
+ uv_buf_t buf;
+ buf.base = &str.front();
+ buf.len = str.length();
+ uv_write(&writeReq, pipeSink, &buf, 1, nullptr);
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ cmUVPipeIStream pin(*loop, pipe[0]);
+ std::string line;
+ std::getline(pin, line);
+ if (line != "Hello world!") {
+ std::cout << "Line was \"" << line << "\", should be \"Hello world!\""
+ << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool testUVStreamRead()
+{
+ int pipe[] = { -1, -1 };
+ if (cmGetPipes(pipe) < 0) {
+ std::cout << "cmGetPipes() returned an error" << std::endl;
+ return false;
+ }
+
+ cm::uv_loop_ptr loop;
+ loop.init();
+ cm::uv_pipe_ptr pipeSink;
+ pipeSink.init(*loop, 0);
+ uv_pipe_open(pipeSink, pipe[1]);
+
+ std::string str = "Hello world!";
+ uv_write_t writeReq;
+ uv_buf_t buf;
+ buf.base = &str.front();
+ buf.len = str.length();
+ uv_write(&writeReq, pipeSink, &buf, 1, nullptr);
+ uv_run(loop, UV_RUN_DEFAULT);
+ pipeSink.reset();
+
+ cm::uv_pipe_ptr pipeSource;
+ pipeSource.init(*loop, 0);
+ uv_pipe_open(pipeSource, pipe[0]);
+
+ std::string output;
+ bool finished = false;
+ cmUVStreamRead(
+ pipeSource,
+ [&output](std::vector<char> data) { cm::append(output, data); },
+ [&output, &finished]() {
+ if (output != "Hello world!") {
+ std::cout << "Output was \"" << output
+ << "\", should be \"Hello world!\"" << std::endl;
+ return;
+ }
+ finished = true;
+ });
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ if (!finished) {
+ std::cout << "finished was not set" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
int testUVStreambuf(int argc, char** const argv)
{
if (argc < 2) {
@@ -454,5 +541,15 @@ int testUVStreambuf(int argc, char** const argv)
return -1;
}
+ if (!testUVPipeIStream()) {
+ std::cout << "While executing testUVPipeIStream().\n";
+ return -1;
+ }
+
+ if (!testUVStreamRead()) {
+ std::cout << "While executing testUVPipeIStream().\n";
+ return -1;
+ }
+
return 0;
}
diff --git a/Utilities/std/cmext/algorithm b/Utilities/std/cmext/algorithm
index 11514fc..46377f4 100644
--- a/Utilities/std/cmext/algorithm
+++ b/Utilities/std/cmext/algorithm
@@ -16,6 +16,7 @@
#if defined(__SUNPRO_CC) && defined(__sparc)
# include <list>
+# include <string>
# include <vector>
#endif
@@ -67,11 +68,15 @@ namespace cm {
APPEND_TWO(C1, C2) \
APPEND_TWO(C2, C1)
-// For now, manage only support for std::vector and std::list.
-// Other sequential container support can be added if needed.
+// For now, manage only support for std::vector, std::list, and
+// std::basic_string. Other sequential container support can be added if
+// needed.
APPEND(std::vector)
APPEND(std::list)
+APPEND(std::basic_string)
APPEND_MIX(std::vector, std::list)
+APPEND_MIX(std::vector, std::basic_string)
+APPEND_MIX(std::list, std::basic_string)
# undef APPEND
# undef APPEND_MIX