Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / cmUVStream.h
blobdb051b8444ebbc5852688b66b5776a1523222e2d
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #pragma once
5 #include <cassert>
6 #include <functional>
7 #include <istream>
9 #include <cm/memory>
11 #include <cm3p/uv.h>
13 #include "cmUVHandlePtr.h"
14 #include "cmUVStreambuf.h"
16 template <typename CharT, typename Traits = std::char_traits<CharT>>
17 class cmBasicUVIStream : public std::basic_istream<CharT>
19 public:
20 cmBasicUVIStream();
21 cmBasicUVIStream(uv_stream_t* stream);
23 bool is_open() const;
25 void open(uv_stream_t* stream);
27 void close();
29 private:
30 cmBasicUVStreambuf<CharT, Traits> Buffer;
33 template <typename CharT, typename Traits>
34 cmBasicUVIStream<CharT, Traits>::cmBasicUVIStream()
35 : std::basic_istream<CharT, Traits>(&this->Buffer)
39 template <typename CharT, typename Traits>
40 cmBasicUVIStream<CharT, Traits>::cmBasicUVIStream(uv_stream_t* stream)
41 : cmBasicUVIStream()
43 this->open(stream);
46 template <typename CharT, typename Traits>
47 bool cmBasicUVIStream<CharT, Traits>::is_open() const
49 return this->Buffer.is_open();
52 template <typename CharT, typename Traits>
53 void cmBasicUVIStream<CharT, Traits>::open(uv_stream_t* stream)
55 this->Buffer.open(stream);
58 template <typename CharT, typename Traits>
59 void cmBasicUVIStream<CharT, Traits>::close()
61 this->Buffer.close();
64 using cmUVIStream = cmBasicUVIStream<char>;
66 template <typename CharT, typename Traits = std::char_traits<CharT>>
67 class cmBasicUVPipeIStream : public cmBasicUVIStream<CharT, Traits>
69 public:
70 cmBasicUVPipeIStream();
71 cmBasicUVPipeIStream(uv_loop_t& loop, int fd);
73 using cmBasicUVIStream<CharT, Traits>::is_open;
75 void open(uv_loop_t& loop, int fd);
77 void close();
79 private:
80 cm::uv_pipe_ptr Pipe;
83 template <typename CharT, typename Traits>
84 cmBasicUVPipeIStream<CharT, Traits>::cmBasicUVPipeIStream() = default;
86 template <typename CharT, typename Traits>
87 cmBasicUVPipeIStream<CharT, Traits>::cmBasicUVPipeIStream(uv_loop_t& loop,
88 int fd)
90 this->open(loop, fd);
93 template <typename CharT, typename Traits>
94 void cmBasicUVPipeIStream<CharT, Traits>::open(uv_loop_t& loop, int fd)
96 this->Pipe.init(loop, 0);
97 uv_pipe_open(this->Pipe, fd);
98 this->cmBasicUVIStream<CharT, Traits>::open(this->Pipe);
101 template <typename CharT, typename Traits>
102 void cmBasicUVPipeIStream<CharT, Traits>::close()
104 this->cmBasicUVIStream<CharT, Traits>::close();
105 this->Pipe.reset();
108 using cmUVPipeIStream = cmBasicUVPipeIStream<char>;
110 class cmUVStreamReadHandle
112 private:
113 std::vector<char> Buffer;
114 std::function<void(std::vector<char>)> OnRead;
115 std::function<void()> OnFinish;
117 template <typename ReadCallback, typename FinishCallback>
118 friend std::unique_ptr<cmUVStreamReadHandle> cmUVStreamRead(
119 uv_stream_t* stream, ReadCallback onRead, FinishCallback onFinish);
122 template <typename ReadCallback, typename FinishCallback>
123 std::unique_ptr<cmUVStreamReadHandle> cmUVStreamRead(uv_stream_t* stream,
124 ReadCallback onRead,
125 FinishCallback onFinish)
127 auto handle = cm::make_unique<cmUVStreamReadHandle>();
128 handle->OnRead = std::move(onRead);
129 handle->OnFinish = std::move(onFinish);
131 stream->data = handle.get();
132 uv_read_start(
133 stream,
134 [](uv_handle_t* s, std::size_t suggestedSize, uv_buf_t* buffer) {
135 auto* data = static_cast<cmUVStreamReadHandle*>(s->data);
136 data->Buffer.resize(suggestedSize);
137 buffer->base = data->Buffer.data();
138 buffer->len = suggestedSize;
140 [](uv_stream_t* s, ssize_t nread, const uv_buf_t* buffer) {
141 auto* data = static_cast<cmUVStreamReadHandle*>(s->data);
142 if (nread > 0) {
143 (void)buffer;
144 assert(buffer->base == data->Buffer.data());
145 data->Buffer.resize(nread);
146 data->OnRead(std::move(data->Buffer));
147 } else if (nread < 0 /*|| nread == UV_EOF*/) {
148 data->OnFinish();
149 uv_read_stop(s);
153 return handle;