/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once #include #include #include #include #include #include "cmUVHandlePtr.h" #include "cmUVStreambuf.h" template > class cmBasicUVIStream : public std::basic_istream { public: cmBasicUVIStream(); cmBasicUVIStream(uv_stream_t* stream); bool is_open() const; void open(uv_stream_t* stream); void close(); private: cmBasicUVStreambuf Buffer; }; template cmBasicUVIStream::cmBasicUVIStream() : std::basic_istream(&this->Buffer) { } template cmBasicUVIStream::cmBasicUVIStream(uv_stream_t* stream) : cmBasicUVIStream() { this->open(stream); } template bool cmBasicUVIStream::is_open() const { return this->Buffer.is_open(); } template void cmBasicUVIStream::open(uv_stream_t* stream) { this->Buffer.open(stream); } template void cmBasicUVIStream::close() { this->Buffer.close(); } using cmUVIStream = cmBasicUVIStream; template > class cmBasicUVPipeIStream : public cmBasicUVIStream { public: cmBasicUVPipeIStream(); cmBasicUVPipeIStream(uv_loop_t& loop, int fd); using cmBasicUVIStream::is_open; void open(uv_loop_t& loop, int fd); void close(); private: cm::uv_pipe_ptr Pipe; }; template cmBasicUVPipeIStream::cmBasicUVPipeIStream() = default; template cmBasicUVPipeIStream::cmBasicUVPipeIStream(uv_loop_t& loop, int fd) { this->open(loop, fd); } template void cmBasicUVPipeIStream::open(uv_loop_t& loop, int fd) { this->Pipe.init(loop, 0); uv_pipe_open(this->Pipe, fd); this->cmBasicUVIStream::open(this->Pipe); } template void cmBasicUVPipeIStream::close() { this->cmBasicUVIStream::close(); this->Pipe.reset(); } using cmUVPipeIStream = cmBasicUVPipeIStream; class cmUVStreamReadHandle { private: std::vector Buffer; std::function)> OnRead; std::function OnFinish; template friend std::unique_ptr cmUVStreamRead( uv_stream_t* stream, ReadCallback onRead, FinishCallback onFinish); }; template std::unique_ptr cmUVStreamRead(uv_stream_t* stream, ReadCallback onRead, FinishCallback onFinish) { auto handle = cm::make_unique(); handle->OnRead = std::move(onRead); handle->OnFinish = std::move(onFinish); stream->data = handle.get(); uv_read_start( stream, [](uv_handle_t* s, std::size_t suggestedSize, uv_buf_t* buffer) { auto* data = static_cast(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(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); } }); return handle; }