container_sink.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2. <HTML>
  3. <HEAD>
  4. <TITLE>Tutorial</TITLE>
  5. <LINK REL="stylesheet" HREF="../../../../boost.css">
  6. <LINK REL="stylesheet" HREF="../theme/iostreams.css">
  7. </HEAD>
  8. <BODY>
  9. <!-- Begin Banner -->
  10. <H1 CLASS="title">Tutorial</H1>
  11. <HR CLASS="banner">
  12. <!-- End Banner -->
  13. <!-- Begin Nav -->
  14. <DIV CLASS='nav'>
  15. <A HREF='container_source.html'><IMG BORDER=0 WIDTH=19 HEIGHT=19 SRC='../../../../doc/src/images/prev.png'></A>
  16. <A HREF='tutorial.html'><IMG BORDER=0 WIDTH=19 HEIGHT=19 SRC='../../../../doc/src/images/up.png'></A>
  17. <A HREF='container_device.html'><IMG BORDER=0 WIDTH=19 HEIGHT=19 SRC='../../../../doc/src/images/next.png'></A>
  18. </DIV>
  19. <!-- End Nav -->
  20. <A NAME="container_sink"></A>
  21. <H2>2.1.3. Writing a <CODE>container_sink</CODE></H2>
  22. <P>Suppose you want to write a Device for appending characters to an STL container. A Device which only supports writing is called a <A HREF="../concepts/sink.html">Sink</A>. A typical narrow-character Sink looks like this:
  23. <PRE CLASS="broken_ie"><SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS="literal">&lt;iosfwd&gt;</SPAN> <SPAN CLASS='comment'>// streamsize</SPAN>
  24. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../../../boost/iostreams/categories.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/categories.hpp&gt;</SPAN></A> <SPAN CLASS='comment'>// sink_tag
  25. </SPAN>
  26. <SPAN CLASS='keyword'>namespace</SPAN> io = boost::iostreams;
  27. <SPAN CLASS='keyword'>class</SPAN> my_sink {
  28. <SPAN CLASS='keyword'>public</SPAN>:
  29. <SPAN CLASS='keyword'>typedef</SPAN> <SPAN CLASS='keyword'>char</SPAN> char_type;
  30. <SPAN CLASS='keyword'>typedef</SPAN> sink_tag category;
  31. std::streamsize write(const <SPAN CLASS='keyword'>char</SPAN>* s, std::streamsize n)
  32. {
  33. <SPAN CLASS='comment'>// Write up to n characters to the underlying </SPAN>
  34. <SPAN CLASS='comment'>// data sink into the buffer s, returning the </SPAN>
  35. <SPAN CLASS='comment'>// number of characters written</SPAN>
  36. }
  37. <SPAN CLASS='comment'>/* Other members */</SPAN>
  38. };</PRE>
  39. <P>Here the member type <A HREF="../guide/traits.html#char_type"><CODE>char_type</CODE></A> indicates the type of characters handled by my_source, which will almost always be <CODE>char</CODE> or <CODE>wchar_t</CODE>. The member type <A HREF="../guide/traits.html#char_type">category</A> indicates which of the fundamental i/o operations are supported by the device. The category tag <A HREF="../guide/traits.html#category_tags"><CODE>sink_tag</CODE></A> indicates that only <A HREF="../functions/write.html"><CODE>write</CODE></A> is supported.</P>
  40. <P>The member function <CODE>write</CODE> writes up to <CODE>n</CODE> character into the buffer <CODE>s</CODE> and returns the number of character written. In general, <CODE>write</CODE> may return fewer characters than requested, in which case the Sink is call <I>non-blocking</I>. Non-blocking Devices do not interact well with stanard streams and stream buffers, however, so most devices should be <A HREF="../concepts/blocking.html">Blocking</A>. <I>See</I> <A HREF="../guide/asynchronous.html">Asynchronous and Non-Blocking I/O</A>.</P>
  41. <P>You could also write the above example as follows:</P>
  42. <PRE CLASS="broken_ie"><SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../../../boost/iostreams/concepts.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/concepts.hpp&gt;</SPAN></A> <SPAN CLASS='comment'>// sink</SPAN>
  43. <SPAN CLASS='keyword'>class</SPAN> my_sink : <SPAN CLASS='keyword'>public</SPAN> sink {
  44. <SPAN CLASS='keyword'>public</SPAN>:
  45. std::streamsize write(const <SPAN CLASS='keyword'>char</SPAN>* s, std::streamsize n);
  46. <SPAN CLASS='comment'>/* Other members */</SPAN>
  47. };</PRE>
  48. <P>Here <A HREF="../classes/device.html#synopsis"><CODE>sink</CODE></A> is a convenience base class which provides the member types <CODE>char_type</CODE> and <CODE>category</CODE>, as well as no-op implementations of member functions <CODE>close</CODE> and <CODE>imbue</CODE>, not needed here.
  49. <P>You're now ready to write your <CODE>container_sink</CODE>.</P>
  50. <PRE CLASS="broken_ie"><SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;algorithm&gt;</SPAN> <SPAN CLASS='comment'>// copy, min</SPAN>
  51. <SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;iosfwd&gt;</SPAN> <SPAN CLASS='comment'>// streamsize</SPAN>
  52. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS='header' HREF="../../../../boost/iostreams/categories.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/categories.hpp&gt;</SPAN></A> <SPAN CLASS='comment'>// sink_tag</SPAN>
  53. <SPAN CLASS='keyword'>namespace</SPAN> boost { <SPAN CLASS='keyword'>namespace</SPAN> iostreams { <SPAN CLASS='keyword'>namespace</SPAN> example {
  54. <SPAN CLASS='keyword'>template</SPAN>&lt;<SPAN CLASS='keyword'>typename</SPAN> Container&gt;
  55. <SPAN CLASS='keyword'>class</SPAN> container_sink {
  56. <SPAN CLASS='keyword'>public</SPAN>:
  57. <SPAN CLASS='keyword'>typedef</SPAN> <SPAN CLASS='keyword'>typename</SPAN> Container::value_type char_type;
  58. <SPAN CLASS='keyword'>typedef</SPAN> sink_tag category;
  59. container_sink(Container&amp; container) : container_(container) { }
  60. std::streamsize write(const char_type* s, std::streamsize n)
  61. {
  62. container_.insert(container_.end(), s, s + n);
  63. <SPAN CLASS='keyword'>return</SPAN> n;
  64. }
  65. Container&amp; container() { return container_; }
  66. <SPAN CLASS='keyword'>private</SPAN>:
  67. Container&amp; container_;
  68. };
  69. } } } <SPAN CLASS='comment'>// End namespace boost::iostreams:example</SPAN></PRE>
  70. <P>Here, note that</P>
  71. <UL>
  72. <LI>The member type <CODE>char_type</CODE> is defined to be equal to the containers's <CODE>value_type</CODE>;
  73. <LI>The member type <CODE>category</CODE> tells the Iostreams library that <CODE>container_sink</CODE> is a model of <A HREF="../concepts/sink.html">Sink</A>;
  74. <LI>A <CODE>container_sink</CODE> can be constructed from a instance of <CODE>Container</CODE>, which is passed and stored by reference, and accessible <I>via</I> the member function <CODE>container()</CODE>; and
  75. <LI>The implementation of <CODE>write()</CODE> simply appends the characters in the specified buffer to the underlying container using the container's <CODE>insert</CODE> funcion,
  76. </UL>
  77. <P>You can write to a container_sink as follows</P>
  78. <PRE CLASS="broken_ie"><SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;cassert&gt;</SPAN>
  79. <SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;string&gt;</SPAN>
  80. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../../../boost/iostreams/stream.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/stream.hpp&gt;</SPAN></A>
  81. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../example/container_device.hpp"><SPAN CLASS='literal'>&lt;libs/iostreams/example/container_device.hpp&gt;</SPAN></A> <SPAN CLASS='comment'>// container_sink</SPAN>
  82. <SPAN CLASS='keyword'>namespace</SPAN> io = boost::iostreams;
  83. <SPAN CLASS='keyword'>namespace</SPAN> ex = boost::iostreams::example;
  84. <SPAN CLASS='keyword'>int</SPAN> main()
  85. {
  86. <SPAN CLASS='keyword'>using</SPAN> <SPAN CLASS='keyword'>namespace</SPAN> std;
  87. <SPAN CLASS='keyword'>typedef</SPAN> ex::container_sink&lt;string&gt; string_sink;
  88. string result;
  89. io::stream&lt;string_sink&gt; out(result);
  90. out &lt;&lt; <SPAN CLASS='literal'>"Hello World!"</SPAN>;
  91. out.flush();
  92. assert(result == <SPAN CLASS='literal'>"Hello World!"</SPAN>);
  93. }</PRE>
  94. <P>Note that the Iostreams library provides buffering by default. Consequently, the stream <CODE>out</CODE> must be flushed before the characters written are guaranteed to be reflected in the underlying <CODE>string</CODE>.
  95. <P>Finally, I should mention that the Iostreams library offers easier ways to append to an STL-compatible container.
  96. First, OutputIterators can be added directly to <A HREF="../guide/filtering_streams.html">filtering streams and stream buffers</A>. So you could write:</P>
  97. <PRE CLASS="broken_ie"><SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;cassert&gt;</SPAN>
  98. <SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;iterator&gt;</SPAN> <SPAN CLASS='comment'>// back_inserter</SPAN>
  99. <SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;string&gt;</SPAN>
  100. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../../../boost/iostreams/filtering_stream.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/filtering_stream.hpp&gt;</SPAN></A>
  101. <SPAN CLASS='keyword'>namespace</SPAN> io = boost::iostreams;
  102. <SPAN CLASS='keyword'>int</SPAN> main()
  103. {
  104. <SPAN CLASS='keyword'>using</SPAN> <SPAN CLASS='keyword'>namespace</SPAN> std;
  105. string result;
  106. io::filtering_ostream out(back_inserter(result));
  107. out &lt;&lt; <SPAN CLASS='literal'>"Hello World!"</SPAN>;
  108. out.flush();
  109. assert(result == <SPAN CLASS='literal'>"Hello World!"</SPAN>);
  110. }</PRE>
  111. <P>Second, the Iostreams library provides a version of <CODE>back_inserter</CODE> that is somewhat more efficient than <CODE>std::back_inserter</CODE> because the Sink it returns uses <CODE>insert</CODE> rather than <CODE>push_back</CODE>. So you could write:</P>
  112. <PRE CLASS="broken_ie"><SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;cassert&gt;</SPAN>
  113. <SPAN CLASS='preprocessor'>#include</SPAN> <SPAN CLASS='literal'>&lt;string&gt;</SPAN>
  114. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../../../boost/iostreams/device/back_inserter.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/device/back_inserter.hpp&gt;</SPAN></A>
  115. <SPAN CLASS='preprocessor'>#include</SPAN> <A CLASS="HEADER" HREF="../../../../boost/iostreams/filtering_stream.hpp"><SPAN CLASS='literal'>&lt;boost/iostreams/filtering_stream.hpp&gt;</SPAN></A>
  116. <SPAN CLASS='keyword'>namespace</SPAN> io = boost::iostreams;
  117. <SPAN CLASS='keyword'>int</SPAN> main()
  118. {
  119. <SPAN CLASS='keyword'>using</SPAN> <SPAN CLASS='keyword'>namespace</SPAN> std;
  120. string result;
  121. io::filtering_ostream out(io::back_inserter(result));
  122. out &lt;&lt; <SPAN CLASS='literal'>"Hello World!"</SPAN>;
  123. out.flush();
  124. assert(result == <SPAN CLASS='literal'>"Hello World!"</SPAN>);
  125. }</PRE>
  126. <!-- Begin Nav -->
  127. <DIV CLASS='nav'>
  128. <A HREF='container_source.html'><IMG BORDER=0 WIDTH=19 HEIGHT=19 SRC='../../../../doc/src/images/prev.png'></A>
  129. <A HREF='tutorial.html'><IMG BORDER=0 WIDTH=19 HEIGHT=19 SRC='../../../../doc/src/images/up.png'></A>
  130. <A HREF='container_device.html'><IMG BORDER=0 WIDTH=19 HEIGHT=19 SRC='../../../../doc/src/images/next.png'></A>
  131. </DIV>
  132. <!-- End Nav -->
  133. <!-- Begin Footer -->
  134. <HR>
  135. <P CLASS="copyright">&copy; Copyright 2008 <a href="http://www.coderage.com/" target="_top">CodeRage, LLC</a><br/>&copy; Copyright 2004-2007 <a href="https://www.boost.org/users/people/jonathan_turkanis.html" target="_top">Jonathan Turkanis</a></P>
  136. <P CLASS="copyright">
  137. Use, modification, and distribution are subject to the Boost Software License, Version 2.0. (See accompanying file <A HREF="../../../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at <A HREF="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>)
  138. </P>
  139. <!-- End Footer -->
  140. </BODY>