output_iterator.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM)
  6. #define BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <iterator>
  11. #include <vector>
  12. #include <algorithm>
  13. #include <boost/config.hpp>
  14. #include <boost/noncopyable.hpp>
  15. #include <boost/mpl/if.hpp>
  16. #include <boost/spirit/home/karma/generator.hpp>
  17. #include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
  18. #include <boost/spirit/home/support/unused.hpp>
  19. #if defined(BOOST_MSVC) && defined(BOOST_SPIRIT_UNICODE)
  20. #include <boost/spirit/home/support/char_encoding/unicode.hpp>
  21. #endif
  22. namespace boost { namespace spirit { namespace karma { namespace detail
  23. {
  24. ///////////////////////////////////////////////////////////////////////////
  25. // This class is used to keep track of the current position in the output.
  26. ///////////////////////////////////////////////////////////////////////////
  27. class position_sink
  28. {
  29. public:
  30. position_sink() : count(0), line(1), column(1) {}
  31. void tidy() { count = 0; line = 1; column = 1; }
  32. template <typename T>
  33. void output(T const& value)
  34. {
  35. ++count;
  36. if (value == '\n') {
  37. ++line;
  38. column = 1;
  39. }
  40. else {
  41. ++column;
  42. }
  43. }
  44. std::size_t get_count() const { return count; }
  45. std::size_t get_line() const { return line; }
  46. std::size_t get_column() const { return column; }
  47. private:
  48. std::size_t count;
  49. std::size_t line;
  50. std::size_t column;
  51. };
  52. ///////////////////////////////////////////////////////////////////////////
  53. struct position_policy
  54. {
  55. position_policy() {}
  56. position_policy(position_policy const& rhs)
  57. : track_position_data(rhs.track_position_data) {}
  58. template <typename T>
  59. void output(T const& value)
  60. {
  61. // track position in the output
  62. track_position_data.output(value);
  63. }
  64. // return the current count in the output
  65. std::size_t get_out_count() const
  66. {
  67. return track_position_data.get_count();
  68. }
  69. // return the current line in the output
  70. std::size_t get_line() const
  71. {
  72. return track_position_data.get_line();
  73. }
  74. // return the current column in the output
  75. std::size_t get_column() const
  76. {
  77. return track_position_data.get_column();
  78. }
  79. private:
  80. position_sink track_position_data; // for position tracking
  81. };
  82. struct no_position_policy
  83. {
  84. no_position_policy() {}
  85. no_position_policy(no_position_policy const&) {}
  86. template <typename T>
  87. void output(T const& /*value*/) {}
  88. };
  89. ///////////////////////////////////////////////////////////////////////////
  90. // This class is used to count the number of characters streamed into the
  91. // output.
  92. ///////////////////////////////////////////////////////////////////////////
  93. template <typename OutputIterator>
  94. class counting_sink : boost::noncopyable
  95. {
  96. public:
  97. counting_sink(OutputIterator& sink_, std::size_t count_ = 0
  98. , bool enabled = true)
  99. : count(count_), initial_count(count), prev_count(0), sink(sink_)
  100. {
  101. prev_count = sink.chain_counting(enabled ? this : NULL);
  102. }
  103. ~counting_sink()
  104. {
  105. if (prev_count) // propagate count
  106. prev_count->update_count(count-initial_count);
  107. sink.chain_counting(prev_count);
  108. }
  109. void output()
  110. {
  111. ++count;
  112. }
  113. std::size_t get_count() const { return count; }
  114. // propagate count from embedded counters
  115. void update_count(std::size_t c)
  116. {
  117. count += c;
  118. }
  119. private:
  120. std::size_t count;
  121. std::size_t initial_count;
  122. counting_sink* prev_count; // previous counter in chain
  123. OutputIterator& sink;
  124. };
  125. ///////////////////////////////////////////////////////////////////////////
  126. template <typename OutputIterator>
  127. struct counting_policy
  128. {
  129. public:
  130. counting_policy() : count(NULL) {}
  131. counting_policy(counting_policy const& rhs) : count(rhs.count) {}
  132. // functions related to counting
  133. counting_sink<OutputIterator>* chain_counting(
  134. counting_sink<OutputIterator>* count_data)
  135. {
  136. counting_sink<OutputIterator>* prev_count = count;
  137. count = count_data;
  138. return prev_count;
  139. }
  140. template <typename T>
  141. void output(T const&)
  142. {
  143. // count characters, if appropriate
  144. if (NULL != count)
  145. count->output();
  146. }
  147. private:
  148. counting_sink<OutputIterator>* count; // for counting
  149. };
  150. struct no_counting_policy
  151. {
  152. no_counting_policy() {}
  153. no_counting_policy(no_counting_policy const&) {}
  154. template <typename T>
  155. void output(T const& /*value*/) {}
  156. };
  157. ///////////////////////////////////////////////////////////////////////////
  158. // The following classes are used to intercept the output into a buffer
  159. // allowing to do things like alignment, character escaping etc.
  160. ///////////////////////////////////////////////////////////////////////////
  161. class buffer_sink : boost::noncopyable
  162. {
  163. // wchar_t is only 16-bits on Windows. If BOOST_SPIRIT_UNICODE is
  164. // defined, the character type is 32-bits wide so we need to make
  165. // sure the buffer is at least that wide.
  166. #if (defined(_WIN32) || defined(__CYGWIN__)) && defined(BOOST_SPIRIT_UNICODE)
  167. typedef spirit::char_encoding::unicode::char_type buffer_char_type;
  168. #else
  169. typedef wchar_t buffer_char_type;
  170. #endif
  171. public:
  172. buffer_sink()
  173. : width(0) {}
  174. ~buffer_sink()
  175. {
  176. tidy();
  177. }
  178. void enable(std::size_t width_)
  179. {
  180. tidy(); // release existing buffer
  181. width = (width_ == std::size_t(-1)) ? 0 : width_;
  182. buffer.reserve(width);
  183. }
  184. void tidy()
  185. {
  186. buffer.clear();
  187. width = 0;
  188. }
  189. template <typename T>
  190. void output(T const& value)
  191. {
  192. BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(buffer_char_type));
  193. buffer.push_back(value);
  194. }
  195. template <typename OutputIterator_>
  196. bool copy(OutputIterator_& sink, std::size_t maxwidth) const
  197. {
  198. #if defined(BOOST_MSVC)
  199. #pragma warning(push)
  200. #pragma warning(disable: 4267)
  201. #endif
  202. typename std::basic_string<buffer_char_type>::const_iterator end =
  203. buffer.begin() + (std::min)(buffer.size(), maxwidth);
  204. #if defined(BOOST_MSVC)
  205. #pragma warning(pop)
  206. #endif
  207. std::copy(buffer.begin(), end, sink);
  208. return true;
  209. }
  210. template <typename RestIterator>
  211. bool copy_rest(RestIterator& sink, std::size_t start_at) const
  212. {
  213. #if defined(BOOST_MSVC)
  214. #pragma warning(push)
  215. #pragma warning(disable: 4267)
  216. #endif
  217. typename std::basic_string<buffer_char_type>::const_iterator begin =
  218. buffer.begin() + (std::min)(buffer.size(), start_at);
  219. #if defined(BOOST_MSVC)
  220. #pragma warning(pop)
  221. #endif
  222. std::copy(begin, buffer.end(), sink);
  223. return true;
  224. }
  225. std::size_t buffer_size() const
  226. {
  227. return buffer.size();
  228. }
  229. private:
  230. std::size_t width;
  231. std::basic_string<buffer_char_type> buffer;
  232. };
  233. ///////////////////////////////////////////////////////////////////////////
  234. struct buffering_policy
  235. {
  236. public:
  237. buffering_policy() : buffer(NULL) {}
  238. buffering_policy(buffering_policy const& rhs) : buffer(rhs.buffer) {}
  239. // functions related to buffering
  240. buffer_sink* chain_buffering(buffer_sink* buffer_data)
  241. {
  242. buffer_sink* prev_buffer = buffer;
  243. buffer = buffer_data;
  244. return prev_buffer;
  245. }
  246. template <typename T>
  247. bool output(T const& value)
  248. {
  249. // buffer characters, if appropriate
  250. if (NULL != buffer) {
  251. buffer->output(value);
  252. return false;
  253. }
  254. return true;
  255. }
  256. bool has_buffer() const { return NULL != buffer; }
  257. private:
  258. buffer_sink* buffer;
  259. };
  260. struct no_buffering_policy
  261. {
  262. no_buffering_policy() {}
  263. no_buffering_policy(no_buffering_policy const&) {}
  264. template <typename T>
  265. bool output(T const& /*value*/)
  266. {
  267. return true;
  268. }
  269. bool has_buffer() const { return false; }
  270. };
  271. ///////////////////////////////////////////////////////////////////////////
  272. // forward declaration only
  273. template <typename OutputIterator>
  274. struct enable_buffering;
  275. template <typename OutputIterator, typename Properties
  276. , typename Derived = unused_type>
  277. class output_iterator;
  278. ///////////////////////////////////////////////////////////////////////////
  279. template <typename Buffering, typename Counting, typename Tracking>
  280. struct output_iterator_base : Buffering, Counting, Tracking
  281. {
  282. typedef Buffering buffering_policy;
  283. typedef Counting counting_policy;
  284. typedef Tracking tracking_policy;
  285. output_iterator_base() {}
  286. output_iterator_base(output_iterator_base const& rhs)
  287. : buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
  288. {}
  289. template <typename T>
  290. bool output(T const& value)
  291. {
  292. this->counting_policy::output(value);
  293. this->tracking_policy::output(value);
  294. return this->buffering_policy::output(value);
  295. }
  296. };
  297. template <typename Buffering, typename Counting, typename Tracking>
  298. struct disabling_output_iterator : Buffering, Counting, Tracking
  299. {
  300. typedef Buffering buffering_policy;
  301. typedef Counting counting_policy;
  302. typedef Tracking tracking_policy;
  303. disabling_output_iterator() : do_output(true) {}
  304. disabling_output_iterator(disabling_output_iterator const& rhs)
  305. : buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
  306. , do_output(rhs.do_output)
  307. {}
  308. template <typename T>
  309. bool output(T const& value)
  310. {
  311. if (!do_output)
  312. return false;
  313. this->counting_policy::output(value);
  314. this->tracking_policy::output(value);
  315. return this->buffering_policy::output(value);
  316. }
  317. bool do_output;
  318. };
  319. ///////////////////////////////////////////////////////////////////////////
  320. template <typename OutputIterator, typename Properties, typename Derived>
  321. struct make_output_iterator
  322. {
  323. // get the most derived type of this class
  324. typedef typename mpl::if_<
  325. traits::not_is_unused<Derived>, Derived
  326. , output_iterator<OutputIterator, Properties, Derived>
  327. >::type most_derived_type;
  328. enum { properties = Properties::value };
  329. typedef typename mpl::if_c<
  330. (properties & generator_properties::tracking) ? true : false
  331. , position_policy, no_position_policy
  332. >::type tracking_type;
  333. typedef typename mpl::if_c<
  334. (properties & generator_properties::buffering) ? true : false
  335. , buffering_policy, no_buffering_policy
  336. >::type buffering_type;
  337. typedef typename mpl::if_c<
  338. (properties & generator_properties::counting) ? true : false
  339. , counting_policy<most_derived_type>, no_counting_policy
  340. >::type counting_type;
  341. typedef typename mpl::if_c<
  342. (properties & generator_properties::disabling) ? true : false
  343. , disabling_output_iterator<buffering_type, counting_type, tracking_type>
  344. , output_iterator_base<buffering_type, counting_type, tracking_type>
  345. >::type type;
  346. };
  347. ///////////////////////////////////////////////////////////////////////////
  348. // Karma uses an output iterator wrapper for all output operations. This
  349. // is necessary to avoid the dreaded 'scanner business' problem, i.e. the
  350. // dependency of rules and grammars on the used output iterator.
  351. //
  352. // By default the user supplied output iterator is wrapped inside an
  353. // instance of this internal output_iterator class.
  354. //
  355. // This output_iterator class normally just forwards to the embedded user
  356. // supplied iterator. But it is possible to enable additional functionality
  357. // on demand, such as counting, buffering, and position tracking.
  358. ///////////////////////////////////////////////////////////////////////////
  359. template <typename OutputIterator, typename Properties, typename Derived>
  360. class output_iterator
  361. : public make_output_iterator<OutputIterator, Properties, Derived>::type
  362. {
  363. private:
  364. // base iterator type
  365. typedef typename make_output_iterator<
  366. OutputIterator, Properties, Derived>::type base_iterator;
  367. public:
  368. typedef std::output_iterator_tag iterator_category;
  369. typedef void value_type;
  370. typedef void difference_type;
  371. typedef void pointer;
  372. typedef void reference;
  373. explicit output_iterator(OutputIterator& sink_)
  374. : sink(&sink_)
  375. {}
  376. output_iterator(output_iterator const& rhs)
  377. : base_iterator(rhs), sink(rhs.sink)
  378. {}
  379. output_iterator& operator*() { return *this; }
  380. output_iterator& operator++()
  381. {
  382. if (!this->base_iterator::has_buffer())
  383. ++(*sink); // increment only if not buffering
  384. return *this;
  385. }
  386. output_iterator operator++(int)
  387. {
  388. if (!this->base_iterator::has_buffer()) {
  389. output_iterator t(*this);
  390. ++(*sink);
  391. return t;
  392. }
  393. return *this;
  394. }
  395. #if defined(BOOST_MSVC)
  396. // 'argument' : conversion from '...' to '...', possible loss of data
  397. #pragma warning (push)
  398. #pragma warning (disable: 4244)
  399. #endif
  400. template <typename T>
  401. void operator=(T const& value)
  402. {
  403. if (this->base_iterator::output(value))
  404. *(*sink) = value;
  405. }
  406. #if defined(BOOST_MSVC)
  407. #pragma warning (pop)
  408. #endif
  409. // plain output iterators are considered to be good all the time
  410. bool good() const { return true; }
  411. // allow to access underlying output iterator
  412. OutputIterator& base() { return *sink; }
  413. protected:
  414. // this is the wrapped user supplied output iterator
  415. OutputIterator* sink;
  416. };
  417. ///////////////////////////////////////////////////////////////////////////
  418. template <typename T, typename Elem, typename Traits, typename Properties>
  419. class output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
  420. : public output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
  421. , output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties> >
  422. {
  423. private:
  424. typedef output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
  425. , output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
  426. > base_type;
  427. typedef karma::ostream_iterator<T, Elem, Traits> base_iterator_type;
  428. typedef std::basic_ostream<Elem, Traits> ostream_type;
  429. public:
  430. output_iterator(base_iterator_type& sink)
  431. : base_type(sink) {}
  432. ostream_type& get_ostream() { return (*this->sink).get_ostream(); }
  433. ostream_type const& get_ostream() const { return (*this->sink).get_ostream(); }
  434. // expose good bit of underlying stream object
  435. bool good() const { return (*this->sink).get_ostream().good(); }
  436. };
  437. ///////////////////////////////////////////////////////////////////////////
  438. // Helper class for exception safe enabling of character counting in the
  439. // output iterator
  440. ///////////////////////////////////////////////////////////////////////////
  441. template <typename OutputIterator>
  442. struct enable_counting
  443. {
  444. enable_counting(OutputIterator& sink_, std::size_t count = 0)
  445. : count_data(sink_, count) {}
  446. // get number of characters counted since last enable
  447. std::size_t count() const
  448. {
  449. return count_data.get_count();
  450. }
  451. private:
  452. counting_sink<OutputIterator> count_data; // for counting
  453. };
  454. template <typename OutputIterator>
  455. struct disable_counting
  456. {
  457. disable_counting(OutputIterator& sink_)
  458. : count_data(sink_, 0, false) {}
  459. private:
  460. counting_sink<OutputIterator> count_data;
  461. };
  462. ///////////////////////////////////////////////////////////////////////////
  463. // Helper class for exception safe enabling of character buffering in the
  464. // output iterator
  465. ///////////////////////////////////////////////////////////////////////////
  466. template <typename OutputIterator>
  467. struct enable_buffering
  468. {
  469. enable_buffering(OutputIterator& sink_
  470. , std::size_t width = std::size_t(-1))
  471. : sink(sink_), prev_buffer(NULL), enabled(false)
  472. {
  473. buffer_data.enable(width);
  474. prev_buffer = sink.chain_buffering(&buffer_data);
  475. enabled = true;
  476. }
  477. ~enable_buffering()
  478. {
  479. disable();
  480. }
  481. // reset buffer chain to initial state
  482. void disable()
  483. {
  484. if (enabled) {
  485. BOOST_VERIFY(&buffer_data == sink.chain_buffering(prev_buffer));
  486. enabled = false;
  487. }
  488. }
  489. // copy to the underlying sink whatever is in the local buffer
  490. bool buffer_copy(std::size_t maxwidth = std::size_t(-1)
  491. , bool disable_ = true)
  492. {
  493. if (disable_)
  494. disable();
  495. return buffer_data.copy(sink, maxwidth) && sink.good();
  496. }
  497. // return number of characters stored in the buffer
  498. std::size_t buffer_size() const
  499. {
  500. return buffer_data.buffer_size();
  501. }
  502. // copy to the remaining characters to the specified sink
  503. template <typename RestIterator>
  504. bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0) const
  505. {
  506. return buffer_data.copy_rest(sink, start_at);
  507. }
  508. // copy the contents to the given output iterator
  509. template <typename OutputIterator_>
  510. bool buffer_copy_to(OutputIterator_& sink
  511. , std::size_t maxwidth = std::size_t(-1)) const
  512. {
  513. return buffer_data.copy(sink, maxwidth);
  514. }
  515. private:
  516. OutputIterator& sink;
  517. buffer_sink buffer_data; // for buffering
  518. buffer_sink* prev_buffer; // previous buffer in chain
  519. bool enabled;
  520. };
  521. ///////////////////////////////////////////////////////////////////////////
  522. // Helper class for exception safe disabling of output
  523. ///////////////////////////////////////////////////////////////////////////
  524. template <typename OutputIterator>
  525. struct disable_output
  526. {
  527. disable_output(OutputIterator& sink_)
  528. : sink(sink_), prev_do_output(sink.do_output)
  529. {
  530. sink.do_output = false;
  531. }
  532. ~disable_output()
  533. {
  534. sink.do_output = prev_do_output;
  535. }
  536. OutputIterator& sink;
  537. bool prev_do_output;
  538. };
  539. ///////////////////////////////////////////////////////////////////////////
  540. template <typename Sink>
  541. bool sink_is_good(Sink const&)
  542. {
  543. return true; // the general case is always good
  544. }
  545. template <typename OutputIterator, typename Derived>
  546. bool sink_is_good(output_iterator<OutputIterator, Derived> const& sink)
  547. {
  548. return sink.good(); // our own output iterators are handled separately
  549. }
  550. }}}}
  551. #endif