Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

287 lignes
10 KiB

  1. /*!
  2. * \file utl/dev/ostream_dev.h
  3. * \brief Abstract base class interface for output devices of utl.
  4. *
  5. * Copyright (C) 2018 Christos Choutouridis
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation, either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. #ifndef __utl_dev_ostream_dev_h__
  22. #define __utl_dev_ostream_dev_h__
  23. #include <utl/core/impl.h>
  24. #include <utl/core/crtp.h>
  25. #include <utl/dev/dev_iterators.h>
  26. #include <utl/meta/meta.h>
  27. namespace utl {
  28. /*!
  29. * \ingroup Device Interface
  30. * \brief Abstract base classes for output stream devices
  31. */
  32. //!@{
  33. /*!
  34. * \brief
  35. * Template base class for output stream devices using CRTP
  36. *
  37. * This class force a common interface for output stream devices.
  38. * By using this common interface the class implements
  39. * - Stream-like inserting operator
  40. * - Output iterator
  41. * - Const output iterator
  42. * to inherit to implementation.
  43. *
  44. * \param impl_t The CRTP type (the derived/implementation class typename).
  45. * \param data_t The devices base type of data
  46. */
  47. template <typename impl_t, typename data_t>
  48. class ostream_dev {
  49. _CRTP_IMPL(impl_t);
  50. using ostream_dev_t = ostream_dev <impl_t, data_t>; //!< class type syntactic sugar
  51. //! Export types as output device concept demands
  52. //! @{
  53. public:
  54. using data_type = data_t;
  55. using pointer_type = data_t*;
  56. //!@}
  57. using type = ostream_dev_t; //!< Export type as identity meta-function
  58. /*!
  59. * \name Constructor / Destructor
  60. */
  61. //!@{
  62. protected:
  63. ~ostream_dev () = default; //!< \brief Allow destructor from derived only
  64. ostream_dev () = default; //!< \brief A default constructor from derived only
  65. ostream_dev(const ostream_dev_t&) = delete; //!< No copies
  66. ostream_dev_t& operator= (const ostream_dev_t&) = delete; //!< No copy assignments
  67. //!@}
  68. //! \name Common output device interface requirements
  69. //!@{
  70. private:
  71. size_t put_ (const data_t& data) { return impl().put_ (data); }
  72. size_t put_ (const data_t* data, size_t n) {
  73. return impl().put_ (data, n);
  74. }
  75. //!@}
  76. /*!
  77. * \name Common output device interface
  78. */
  79. //!@{
  80. public:
  81. /*!
  82. * \brief
  83. * Put interface. This function should send a single
  84. * data_t object to device.
  85. * \param data The data to send
  86. * \return The number of transmitted data items
  87. * \note
  88. * A successful call should return 1
  89. */
  90. size_t put (const data_t& data) {
  91. return put_ (data);
  92. }
  93. /*!
  94. * \brief
  95. * Put interface. This function should send a stream of
  96. * data_t objects to device.
  97. * \param data Pointer to buffer indenting write to device.
  98. * \param n The number of data of type data_t to send
  99. * \return The number of transmitted items.
  100. */
  101. size_t put (const data_t* data, size_t n) {
  102. return put_ (data, n);
  103. }
  104. //!@}
  105. /*!
  106. * \name Stream operator << interface
  107. */
  108. //!@{
  109. public:
  110. /*!
  111. * \brief
  112. * Template operator<< implementation for for all by value/ref parameters
  113. * \note
  114. * In the case _Src_t size is not an exact multiple of data_t size
  115. * the write data will be truncated and there may be data loss.
  116. * \param src Reference to source data
  117. * \return Reference to this device for chaining
  118. */
  119. template <typename _Src_t>
  120. ostream_dev_t& operator<< (const _Src_t& src) {
  121. static_assert ((sizeof (_Src_t)%sizeof(data_t) == 0),
  122. "Source size must be an integer multiple of device's data size");
  123. put_ (reinterpret_cast<const data_t*>(&src), sizeof(_Src_t)/sizeof(data_t));
  124. return *this;
  125. }
  126. //! Overload to disallow pointer types as source
  127. template <typename _Src_t>
  128. ostream_dev_t& operator<< (_Src_t* src) = delete;
  129. //! Overload for single data_t object
  130. ostream_dev_t& operator<< (const data_t& src) {
  131. put_ (src);
  132. return *this;
  133. }
  134. //ToDo: Add support for c-string, utl::string, ...
  135. //!@}
  136. /*!
  137. * \name STL-like Output iterator interface
  138. */
  139. //!@{
  140. using iterator = ostreamdev_it <ostream_dev_t, data_t>; //!< Iterator
  141. using const_iterator = ostreamdev_it <const ostream_dev_t, data_t>; //!< Const iterator
  142. //!@{ .begin implementation
  143. iterator begin () noexcept { return iterator(this); }
  144. const_iterator begin () const noexcept { return const_iterator(this); }
  145. const_iterator cbegin () const noexcept { return const_iterator(this); }
  146. //!@}
  147. //!@{ .end implementation
  148. iterator end () noexcept { return iterator(); }
  149. const_iterator end () const noexcept { return const_iterator(); }
  150. const_iterator cend () const noexcept { return const_iterator(); }
  151. //!@}
  152. //!@}
  153. };
  154. template <typename data_t>
  155. class ostream_dev<virtual_tag, data_t> {
  156. using ostream_dev_t = ostream_dev <virtual_tag, data_t>; //!< class type syntactic sugar
  157. //! Export types as output device concept demands
  158. //! @{
  159. public:
  160. using data_type = data_t;
  161. using pointer_type = data_t*;
  162. //!@}
  163. using type = ostream_dev_t; //!< Export type as identity meta-function
  164. /*!
  165. * \name Constructor / Destructor
  166. */
  167. //!@{
  168. public:
  169. virtual ~ostream_dev () = default; //!< \brief Virtual destructor
  170. protected:
  171. ostream_dev () = default; //!< \brief A default constructor from derived only
  172. ostream_dev(const ostream_dev_t&) = delete; //!< No copies
  173. ostream_dev_t& operator= (const ostream_dev_t&) = delete; //!< No copy assignments
  174. //!@}
  175. //! \name Common output device interface requirements
  176. //!@{
  177. private:
  178. virtual size_t put_ (const data_t& data) =0;
  179. virtual size_t put_ (const data_t* data, size_t n) =0;
  180. //!@}
  181. /*!
  182. * \name Common output device interface
  183. */
  184. //!@{
  185. public:
  186. /*!
  187. * \brief
  188. * Put interface. This function should send a single
  189. * data_t object to device.
  190. * \param data The data to send
  191. * \return The number of transmitted data items
  192. * \note
  193. * A successful call should return 1
  194. */
  195. size_t put (const data_t& data) {
  196. return put_ (data);
  197. }
  198. /*!
  199. * \brief
  200. * Put interface. This function should send a stream of
  201. * data_t objects to device.
  202. * \param data Pointer to buffer indenting write to device.
  203. * \param n The number of data of type data_t to send
  204. * \return The number of transmitted items.
  205. */
  206. size_t put (const data_t* data, size_t n) {
  207. return put_ (data, n);
  208. }
  209. //!@}
  210. /*!
  211. * \name Stream operator << interface
  212. */
  213. //!@{
  214. public:
  215. /*!
  216. * \brief
  217. * Template operator<< implementation for for all by value/ref parameters
  218. * \note
  219. * In the case _Src_t size is not an exact multiple of data_t size
  220. * the write data will be truncated and there may be data loss.
  221. * \param src Reference to source data
  222. * \return Reference to this device for chaining
  223. */
  224. template <typename _Src_t>
  225. ostream_dev_t& operator<< (const _Src_t& src) {
  226. static_assert ((sizeof (_Src_t)%sizeof(data_t) == 0),
  227. "Source size must be an integer multiple of device's data size");
  228. put_ (reinterpret_cast<const data_t*>(&src), sizeof(_Src_t)/sizeof(data_t));
  229. return *this;
  230. }
  231. //! Overload to disallow pointer types as source
  232. template <typename _Src_t>
  233. ostream_dev_t& operator<< (_Src_t* src) = delete;
  234. //! Overload for single data_t object
  235. ostream_dev_t& operator<< (const data_t& src) {
  236. put_ (src);
  237. return *this;
  238. }
  239. //!@}
  240. /*!
  241. * \name STL-like Output iterator interface
  242. */
  243. //!@{
  244. using iterator = ostreamdev_it <ostream_dev_t, data_t>; //!< Iterator
  245. using const_iterator = ostreamdev_it <const ostream_dev_t, data_t>; //!< Const iterator
  246. //!@{ .begin implementation
  247. iterator begin () noexcept { return iterator(this); }
  248. const_iterator begin () const noexcept { return const_iterator(this); }
  249. const_iterator cbegin () const noexcept { return const_iterator(this); }
  250. //!@}
  251. //!@{ .end implementation
  252. iterator end () noexcept { return iterator(); }
  253. const_iterator end () const noexcept { return const_iterator(); }
  254. const_iterator cend () const noexcept { return const_iterator(); }
  255. //!@}
  256. //!@}
  257. };
  258. //!@}
  259. } //namespace utl
  260. #endif /* #ifndef __utl_dev_out_dev_h__ */