|
- /*!
- * \file utl/dev/ostream_dev.h
- * \brief Abstract base class interface for output devices of utl.
- *
- * Copyright (C) 2018 Christos Choutouridis
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #ifndef __utl_dev_ostream_dev_h__
- #define __utl_dev_ostream_dev_h__
-
- #include <utl/core/impl.h>
- #include <utl/core/crtp.h>
- #include <utl/dev/dev_iterators.h>
- #include <utl/meta/meta.h>
-
- namespace utl {
-
- /*!
- * \ingroup Device Interface
- * \brief Abstract base classes for output stream devices
- */
- //!@{
-
- /*!
- * \brief
- * Template base class for output stream devices using CRTP
- *
- * This class force a common interface for output stream devices.
- * By using this common interface the class implements
- * - Stream-like inserting operator
- * - Output iterator
- * - Const output iterator
- * to inherit to implementation.
- *
- * \param impl_t The CRTP type (the derived/implementation class typename).
- * \param data_t The devices base type of data
- */
- template <typename impl_t, typename data_t>
- class ostream_dev {
- _CRTP_IMPL(impl_t);
- using ostream_dev_t = ostream_dev <impl_t, data_t>; //!< class type syntactic sugar
-
- //! Export types as output device concept demands
- //! @{
- public:
- using data_type = data_t;
- using pointer_type = data_t*;
- //!@}
- using type = ostream_dev_t; //!< Export type as identity meta-function
- /*!
- * \name Constructor / Destructor
- */
- //!@{
- protected:
- ~ostream_dev () = default; //!< \brief Allow destructor from derived only
- ostream_dev () = default; //!< \brief A default constructor from derived only
- ostream_dev(const ostream_dev_t&) = delete; //!< No copies
- ostream_dev_t& operator= (const ostream_dev_t&) = delete; //!< No copy assignments
- //!@}
-
- //! \name Common output device interface requirements
- //!@{
- private:
- size_t put_ (const data_t& data) { return impl().put_ (data); }
- size_t put_ (const data_t* data, size_t n) {
- return impl().put_ (data, n);
- }
- //!@}
- /*!
- * \name Common output device interface
- */
- //!@{
- public:
- /*!
- * \brief
- * Put interface. This function should send a single
- * data_t object to device.
- * \param data The data to send
- * \return The number of transmitted data items
- * \note
- * A successful call should return 1
- */
- size_t put (const data_t& data) {
- return put_ (data);
- }
-
- /*!
- * \brief
- * Put interface. This function should send a stream of
- * data_t objects to device.
- * \param data Pointer to buffer indenting write to device.
- * \param n The number of data of type data_t to send
- * \return The number of transmitted items.
- */
- size_t put (const data_t* data, size_t n) {
- return put_ (data, n);
- }
- //!@}
-
- /*!
- * \name Stream operator << interface
- */
- //!@{
- public:
- /*!
- * \brief
- * Template operator<< implementation for for all by value/ref parameters
- * \note
- * In the case _Src_t size is not an exact multiple of data_t size
- * the write data will be truncated and there may be data loss.
- * \param src Reference to source data
- * \return Reference to this device for chaining
- */
- template <typename _Src_t>
- ostream_dev_t& operator<< (const _Src_t& src) {
- static_assert ((sizeof (_Src_t)%sizeof(data_t) == 0),
- "Source size must be an integer multiple of device's data size");
- put_ (reinterpret_cast<const data_t*>(&src), sizeof(_Src_t)/sizeof(data_t));
- return *this;
- }
- //! Overload to disallow pointer types as source
- template <typename _Src_t>
- ostream_dev_t& operator<< (_Src_t* src) = delete;
-
- //! Overload for single data_t object
- ostream_dev_t& operator<< (const data_t& src) {
- put_ (src);
- return *this;
- }
- //ToDo: Add support for c-string, utl::string, ...
- //!@}
-
- /*!
- * \name STL-like Output iterator interface
- */
- //!@{
- using iterator = ostreamdev_it <ostream_dev_t, data_t>; //!< Iterator
- using const_iterator = ostreamdev_it <const ostream_dev_t, data_t>; //!< Const iterator
-
- //!@{ .begin implementation
- iterator begin () noexcept { return iterator(this); }
- const_iterator begin () const noexcept { return const_iterator(this); }
- const_iterator cbegin () const noexcept { return const_iterator(this); }
- //!@}
- //!@{ .end implementation
- iterator end () noexcept { return iterator(); }
- const_iterator end () const noexcept { return const_iterator(); }
- const_iterator cend () const noexcept { return const_iterator(); }
- //!@}
- //!@}
- };
-
-
-
-
-
- template <typename data_t>
- class ostream_dev<virtual_tag, data_t> {
- using ostream_dev_t = ostream_dev <virtual_tag, data_t>; //!< class type syntactic sugar
-
- //! Export types as output device concept demands
- //! @{
- public:
- using data_type = data_t;
- using pointer_type = data_t*;
- //!@}
- using type = ostream_dev_t; //!< Export type as identity meta-function
- /*!
- * \name Constructor / Destructor
- */
- //!@{
- public:
- virtual ~ostream_dev () = default; //!< \brief Virtual destructor
- protected:
- ostream_dev () = default; //!< \brief A default constructor from derived only
- ostream_dev(const ostream_dev_t&) = delete; //!< No copies
- ostream_dev_t& operator= (const ostream_dev_t&) = delete; //!< No copy assignments
- //!@}
-
- //! \name Common output device interface requirements
- //!@{
- private:
- virtual size_t put_ (const data_t& data) =0;
- virtual size_t put_ (const data_t* data, size_t n) =0;
- //!@}
- /*!
- * \name Common output device interface
- */
- //!@{
- public:
- /*!
- * \brief
- * Put interface. This function should send a single
- * data_t object to device.
- * \param data The data to send
- * \return The number of transmitted data items
- * \note
- * A successful call should return 1
- */
- size_t put (const data_t& data) {
- return put_ (data);
- }
-
- /*!
- * \brief
- * Put interface. This function should send a stream of
- * data_t objects to device.
- * \param data Pointer to buffer indenting write to device.
- * \param n The number of data of type data_t to send
- * \return The number of transmitted items.
- */
- size_t put (const data_t* data, size_t n) {
- return put_ (data, n);
- }
- //!@}
-
- /*!
- * \name Stream operator << interface
- */
- //!@{
- public:
- /*!
- * \brief
- * Template operator<< implementation for for all by value/ref parameters
- * \note
- * In the case _Src_t size is not an exact multiple of data_t size
- * the write data will be truncated and there may be data loss.
- * \param src Reference to source data
- * \return Reference to this device for chaining
- */
- template <typename _Src_t>
- ostream_dev_t& operator<< (const _Src_t& src) {
- static_assert ((sizeof (_Src_t)%sizeof(data_t) == 0),
- "Source size must be an integer multiple of device's data size");
- put_ (reinterpret_cast<const data_t*>(&src), sizeof(_Src_t)/sizeof(data_t));
- return *this;
- }
- //! Overload to disallow pointer types as source
- template <typename _Src_t>
- ostream_dev_t& operator<< (_Src_t* src) = delete;
-
- //! Overload for single data_t object
- ostream_dev_t& operator<< (const data_t& src) {
- put_ (src);
- return *this;
- }
- //!@}
-
- /*!
- * \name STL-like Output iterator interface
- */
- //!@{
- using iterator = ostreamdev_it <ostream_dev_t, data_t>; //!< Iterator
- using const_iterator = ostreamdev_it <const ostream_dev_t, data_t>; //!< Const iterator
-
- //!@{ .begin implementation
- iterator begin () noexcept { return iterator(this); }
- const_iterator begin () const noexcept { return const_iterator(this); }
- const_iterator cbegin () const noexcept { return const_iterator(this); }
- //!@}
- //!@{ .end implementation
- iterator end () noexcept { return iterator(); }
- const_iterator end () const noexcept { return const_iterator(); }
- const_iterator cend () const noexcept { return const_iterator(); }
- //!@}
- //!@}
- };
-
-
- //!@}
- } //namespace utl
-
- #endif /* #ifndef __utl_dev_out_dev_h__ */
|