408 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			408 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //
 | ||
|  | // basic_socket_iostream.hpp
 | ||
|  | // ~~~~~~~~~~~~~~~~~~~~~~~~~
 | ||
|  | //
 | ||
|  | // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 | ||
|  | //
 | ||
|  | // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | ||
|  | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | ||
|  | //
 | ||
|  | 
 | ||
|  | #ifndef ASIO_BASIC_SOCKET_IOSTREAM_HPP
 | ||
|  | #define ASIO_BASIC_SOCKET_IOSTREAM_HPP
 | ||
|  | 
 | ||
|  | #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 | ||
|  | # pragma once
 | ||
|  | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 | ||
|  | 
 | ||
|  | #include "asio/detail/config.hpp"
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_NO_IOSTREAM)
 | ||
|  | 
 | ||
|  | #include <istream>
 | ||
|  | #include <ostream>
 | ||
|  | #include "asio/basic_socket_streambuf.hpp"
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | # include "asio/detail/variadic_templates.hpp"
 | ||
|  | 
 | ||
|  | // A macro that should expand to:
 | ||
|  | //   template <typename T1, ..., typename Tn>
 | ||
|  | //   explicit basic_socket_iostream(T1 x1, ..., Tn xn)
 | ||
|  | //     : std::basic_iostream<char>(
 | ||
|  | //         &this->detail::socket_iostream_base<
 | ||
|  | //           Protocol, Clock, WaitTraits>::streambuf_)
 | ||
|  | //   {
 | ||
|  | //     if (rdbuf()->connect(x1, ..., xn) == 0)
 | ||
|  | //       this->setstate(std::ios_base::failbit);
 | ||
|  | //   }
 | ||
|  | // This macro should only persist within this file.
 | ||
|  | 
 | ||
|  | # define ASIO_PRIVATE_CTR_DEF(n) \
 | ||
|  |   template <ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   explicit basic_socket_iostream(ASIO_VARIADIC_BYVAL_PARAMS(n)) \ | ||
|  |     : std::basic_iostream<char>( \ | ||
|  |         &this->detail::socket_iostream_base< \ | ||
|  |           Protocol, Clock, WaitTraits>::streambuf_) \ | ||
|  |   { \ | ||
|  |     this->setf(std::ios_base::unitbuf); \ | ||
|  |     if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \ | ||
|  |       this->setstate(std::ios_base::failbit); \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  | 
 | ||
|  | // A macro that should expand to:
 | ||
|  | //   template <typename T1, ..., typename Tn>
 | ||
|  | //   void connect(T1 x1, ..., Tn xn)
 | ||
|  | //   {
 | ||
|  | //     if (rdbuf()->connect(x1, ..., xn) == 0)
 | ||
|  | //       this->setstate(std::ios_base::failbit);
 | ||
|  | //   }
 | ||
|  | // This macro should only persist within this file.
 | ||
|  | 
 | ||
|  | # define ASIO_PRIVATE_CONNECT_DEF(n) \
 | ||
|  |   template <ASIO_VARIADIC_TPARAMS(n)> \ | ||
|  |   void connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \ | ||
|  |   { \ | ||
|  |     if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \ | ||
|  |       this->setstate(std::ios_base::failbit); \ | ||
|  |   } \ | ||
|  |   /**/ | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | #include "asio/detail/push_options.hpp"
 | ||
|  | 
 | ||
|  | namespace asio { | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | // A separate base class is used to ensure that the streambuf is initialised
 | ||
|  | // prior to the basic_socket_iostream's basic_iostream base class.
 | ||
|  | template <typename Protocol, typename Clock, typename WaitTraits> | ||
|  | class socket_iostream_base | ||
|  | { | ||
|  | protected: | ||
|  |   socket_iostream_base() | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_MOVE)
 | ||
|  |   socket_iostream_base(socket_iostream_base&& other) | ||
|  |     : streambuf_(std::move(other.streambuf_)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   socket_iostream_base(basic_stream_socket<Protocol> s) | ||
|  |     : streambuf_(std::move(s)) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   socket_iostream_base& operator=(socket_iostream_base&& other) | ||
|  |   { | ||
|  |     streambuf_ = std::move(other.streambuf_); | ||
|  |     return *this; | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_MOVE)
 | ||
|  | 
 | ||
|  |   basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_; | ||
|  | }; | ||
|  | 
 | ||
|  | } // namespace detail
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
 | ||
|  | #define ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
 | ||
|  | 
 | ||
|  | // Forward declaration with defaulted arguments.
 | ||
|  | template <typename Protocol, | ||
|  | #if defined(ASIO_HAS_BOOST_DATE_TIME) \
 | ||
|  |   && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) | ||
|  |     typename Clock = boost::posix_time::ptime, | ||
|  |     typename WaitTraits = time_traits<Clock> > | ||
|  | #else // defined(ASIO_HAS_BOOST_DATE_TIME)
 | ||
|  |       // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
 | ||
|  |     typename Clock = chrono::steady_clock, | ||
|  |     typename WaitTraits = wait_traits<Clock> > | ||
|  | #endif // defined(ASIO_HAS_BOOST_DATE_TIME)
 | ||
|  |        // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
 | ||
|  | class basic_socket_iostream; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
 | ||
|  | 
 | ||
|  | /// Iostream interface for a socket.
 | ||
|  | #if defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename Protocol, | ||
|  |     typename Clock = chrono::steady_clock, | ||
|  |     typename WaitTraits = wait_traits<Clock> > | ||
|  | #else // defined(GENERATING_DOCUMENTATION)
 | ||
|  | template <typename Protocol, typename Clock, typename WaitTraits> | ||
|  | #endif // defined(GENERATING_DOCUMENTATION)
 | ||
|  | class basic_socket_iostream | ||
|  |   : private detail::socket_iostream_base<Protocol, Clock, WaitTraits>, | ||
|  |     public std::basic_iostream<char> | ||
|  | { | ||
|  | private: | ||
|  |   // These typedefs are intended keep this class's implementation independent
 | ||
|  |   // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
 | ||
|  | #if defined(ASIO_HAS_BOOST_DATE_TIME) \
 | ||
|  |   && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) | ||
|  |   typedef WaitTraits traits_helper; | ||
|  | #else // defined(ASIO_HAS_BOOST_DATE_TIME)
 | ||
|  |       // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
 | ||
|  |   typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper; | ||
|  | #endif // defined(ASIO_HAS_BOOST_DATE_TIME)
 | ||
|  |        // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
 | ||
|  | 
 | ||
|  | public: | ||
|  |   /// The protocol type.
 | ||
|  |   typedef Protocol protocol_type; | ||
|  | 
 | ||
|  |   /// The endpoint type.
 | ||
|  |   typedef typename Protocol::endpoint endpoint_type; | ||
|  | 
 | ||
|  |   /// The clock type.
 | ||
|  |   typedef Clock clock_type; | ||
|  | 
 | ||
|  | #if defined(GENERATING_DOCUMENTATION)
 | ||
|  |   /// (Deprecated: Use time_point.) The time type.
 | ||
|  |   typedef typename WaitTraits::time_type time_type; | ||
|  | 
 | ||
|  |   /// The time type.
 | ||
|  |   typedef typename WaitTraits::time_point time_point; | ||
|  | 
 | ||
|  |   /// (Deprecated: Use duration.) The duration type.
 | ||
|  |   typedef typename WaitTraits::duration_type duration_type; | ||
|  | 
 | ||
|  |   /// The duration type.
 | ||
|  |   typedef typename WaitTraits::duration duration; | ||
|  | #else
 | ||
|  | # if !defined(ASIO_NO_DEPRECATED)
 | ||
|  |   typedef typename traits_helper::time_type time_type; | ||
|  |   typedef typename traits_helper::duration_type duration_type; | ||
|  | # endif // !defined(ASIO_NO_DEPRECATED)
 | ||
|  |   typedef typename traits_helper::time_type time_point; | ||
|  |   typedef typename traits_helper::duration_type duration; | ||
|  | #endif
 | ||
|  | 
 | ||
|  |   /// Construct a basic_socket_iostream without establishing a connection.
 | ||
|  |   basic_socket_iostream() | ||
|  |     : std::basic_iostream<char>( | ||
|  |         &this->detail::socket_iostream_base< | ||
|  |           Protocol, Clock, WaitTraits>::streambuf_) | ||
|  |   { | ||
|  |     this->setf(std::ios_base::unitbuf); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
 | ||
|  |   /// Construct a basic_socket_iostream from the supplied socket.
 | ||
|  |   explicit basic_socket_iostream(basic_stream_socket<protocol_type> s) | ||
|  |     : detail::socket_iostream_base< | ||
|  |         Protocol, Clock, WaitTraits>(std::move(s)), | ||
|  |       std::basic_iostream<char>( | ||
|  |         &this->detail::socket_iostream_base< | ||
|  |           Protocol, Clock, WaitTraits>::streambuf_) | ||
|  |   { | ||
|  |     this->setf(std::ios_base::unitbuf); | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_STD_IOSTREAM_MOVE) \
 | ||
|  |   || defined(GENERATING_DOCUMENTATION) | ||
|  |   /// Move-construct a basic_socket_iostream from another.
 | ||
|  |   basic_socket_iostream(basic_socket_iostream&& other) | ||
|  |     : detail::socket_iostream_base< | ||
|  |         Protocol, Clock, WaitTraits>(std::move(other)), | ||
|  |       std::basic_iostream<char>(std::move(other)) | ||
|  |   { | ||
|  |     this->set_rdbuf(&this->detail::socket_iostream_base< | ||
|  |           Protocol, Clock, WaitTraits>::streambuf_); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Move-assign a basic_socket_iostream from another.
 | ||
|  |   basic_socket_iostream& operator=(basic_socket_iostream&& other) | ||
|  |   { | ||
|  |     std::basic_iostream<char>::operator=(std::move(other)); | ||
|  |     detail::socket_iostream_base< | ||
|  |         Protocol, Clock, WaitTraits>::operator=(std::move(other)); | ||
|  |     return *this; | ||
|  |   } | ||
|  | #endif // defined(ASIO_HAS_STD_IOSTREAM_MOVE)
 | ||
|  |        //   || defined(GENERATING_DOCUMENTATION)
 | ||
|  | #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
 | ||
|  | 
 | ||
|  | #if defined(GENERATING_DOCUMENTATION)
 | ||
|  |   /// Establish a connection to an endpoint corresponding to a resolver query.
 | ||
|  |   /**
 | ||
|  |    * This constructor automatically establishes a connection based on the | ||
|  |    * supplied resolver query parameters. The arguments are used to construct | ||
|  |    * a resolver query object. | ||
|  |    */ | ||
|  |   template <typename T1, ..., typename TN> | ||
|  |   explicit basic_socket_iostream(T1 t1, ..., TN tn); | ||
|  | #elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  |   template <typename... T> | ||
|  |   explicit basic_socket_iostream(T... x) | ||
|  |     : std::basic_iostream<char>( | ||
|  |         &this->detail::socket_iostream_base< | ||
|  |           Protocol, Clock, WaitTraits>::streambuf_) | ||
|  |   { | ||
|  |     this->setf(std::ios_base::unitbuf); | ||
|  |     if (rdbuf()->connect(x...) == 0) | ||
|  |       this->setstate(std::ios_base::failbit); | ||
|  |   } | ||
|  | #else
 | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CTR_DEF) | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #if defined(GENERATING_DOCUMENTATION)
 | ||
|  |   /// Establish a connection to an endpoint corresponding to a resolver query.
 | ||
|  |   /**
 | ||
|  |    * This function automatically establishes a connection based on the supplied | ||
|  |    * resolver query parameters. The arguments are used to construct a resolver | ||
|  |    * query object. | ||
|  |    */ | ||
|  |   template <typename T1, ..., typename TN> | ||
|  |   void connect(T1 t1, ..., TN tn); | ||
|  | #elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  |   template <typename... T> | ||
|  |   void connect(T... x) | ||
|  |   { | ||
|  |     if (rdbuf()->connect(x...) == 0) | ||
|  |       this->setstate(std::ios_base::failbit); | ||
|  |   } | ||
|  | #else
 | ||
|  |   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CONNECT_DEF) | ||
|  | #endif
 | ||
|  | 
 | ||
|  |   /// Close the connection.
 | ||
|  |   void close() | ||
|  |   { | ||
|  |     if (rdbuf()->close() == 0) | ||
|  |       this->setstate(std::ios_base::failbit); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Return a pointer to the underlying streambuf.
 | ||
|  |   basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const | ||
|  |   { | ||
|  |     return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>( | ||
|  |         &this->detail::socket_iostream_base< | ||
|  |           Protocol, Clock, WaitTraits>::streambuf_); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Get a reference to the underlying socket.
 | ||
|  |   basic_socket<Protocol>& socket() | ||
|  |   { | ||
|  |     return rdbuf()->socket(); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Get the last error associated with the stream.
 | ||
|  |   /**
 | ||
|  |    * @return An \c error_code corresponding to the last error from the stream. | ||
|  |    * | ||
|  |    * @par Example | ||
|  |    * To print the error associated with a failure to establish a connection: | ||
|  |    * @code tcp::iostream s("www.boost.org", "http"); | ||
|  |    * if (!s) | ||
|  |    * { | ||
|  |    *   std::cout << "Error: " << s.error().message() << std::endl; | ||
|  |    * } @endcode | ||
|  |    */ | ||
|  |   const asio::error_code& error() const | ||
|  |   { | ||
|  |     return rdbuf()->error(); | ||
|  |   } | ||
|  | 
 | ||
|  | #if !defined(ASIO_NO_DEPRECATED)
 | ||
|  |   /// (Deprecated: Use expiry().) Get the stream's expiry time as an absolute
 | ||
|  |   /// time.
 | ||
|  |   /**
 | ||
|  |    * @return An absolute time value representing the stream's expiry time. | ||
|  |    */ | ||
|  |   time_point expires_at() const | ||
|  |   { | ||
|  |     return rdbuf()->expires_at(); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_DEPRECATED)
 | ||
|  | 
 | ||
|  |   /// Get the stream's expiry time as an absolute time.
 | ||
|  |   /**
 | ||
|  |    * @return An absolute time value representing the stream's expiry time. | ||
|  |    */ | ||
|  |   time_point expiry() const | ||
|  |   { | ||
|  |     return rdbuf()->expiry(); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Set the stream's expiry time as an absolute time.
 | ||
|  |   /**
 | ||
|  |    * This function sets the expiry time associated with the stream. Stream | ||
|  |    * operations performed after this time (where the operations cannot be | ||
|  |    * completed using the internal buffers) will fail with the error | ||
|  |    * asio::error::operation_aborted. | ||
|  |    * | ||
|  |    * @param expiry_time The expiry time to be used for the stream. | ||
|  |    */ | ||
|  |   void expires_at(const time_point& expiry_time) | ||
|  |   { | ||
|  |     rdbuf()->expires_at(expiry_time); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// Set the stream's expiry time relative to now.
 | ||
|  |   /**
 | ||
|  |    * This function sets the expiry time associated with the stream. Stream | ||
|  |    * operations performed after this time (where the operations cannot be | ||
|  |    * completed using the internal buffers) will fail with the error | ||
|  |    * asio::error::operation_aborted. | ||
|  |    * | ||
|  |    * @param expiry_time The expiry time to be used for the timer. | ||
|  |    */ | ||
|  |   void expires_after(const duration& expiry_time) | ||
|  |   { | ||
|  |     rdbuf()->expires_after(expiry_time); | ||
|  |   } | ||
|  | 
 | ||
|  | #if !defined(ASIO_NO_DEPRECATED)
 | ||
|  |   /// (Deprecated: Use expiry().) Get the stream's expiry time relative to now.
 | ||
|  |   /**
 | ||
|  |    * @return A relative time value representing the stream's expiry time. | ||
|  |    */ | ||
|  |   duration expires_from_now() const | ||
|  |   { | ||
|  |     return rdbuf()->expires_from_now(); | ||
|  |   } | ||
|  | 
 | ||
|  |   /// (Deprecated: Use expires_after().) Set the stream's expiry time relative
 | ||
|  |   /// to now.
 | ||
|  |   /**
 | ||
|  |    * This function sets the expiry time associated with the stream. Stream | ||
|  |    * operations performed after this time (where the operations cannot be | ||
|  |    * completed using the internal buffers) will fail with the error | ||
|  |    * asio::error::operation_aborted. | ||
|  |    * | ||
|  |    * @param expiry_time The expiry time to be used for the timer. | ||
|  |    */ | ||
|  |   void expires_from_now(const duration& expiry_time) | ||
|  |   { | ||
|  |     rdbuf()->expires_from_now(expiry_time); | ||
|  |   } | ||
|  | #endif // !defined(ASIO_NO_DEPRECATED)
 | ||
|  | 
 | ||
|  | private: | ||
|  |   // Disallow copying and assignment.
 | ||
|  |   basic_socket_iostream(const basic_socket_iostream&) ASIO_DELETED; | ||
|  |   basic_socket_iostream& operator=( | ||
|  |       const basic_socket_iostream&) ASIO_DELETED; | ||
|  | }; | ||
|  | 
 | ||
|  | } // namespace asio
 | ||
|  | 
 | ||
|  | #include "asio/detail/pop_options.hpp"
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | # undef ASIO_PRIVATE_CTR_DEF
 | ||
|  | # undef ASIO_PRIVATE_CONNECT_DEF
 | ||
|  | #endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)
 | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_NO_IOSTREAM)
 | ||
|  | 
 | ||
|  | #endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP
 |