/Src/Dependencies/Boost/boost/spirit/home/karma/detail/output_iterator.hpp

http://hadesmem.googlecode.com/ · C++ Header · 616 lines · 462 code · 88 blank · 66 comment · 18 complexity · 9ba993446e2da004330a84d25a4cc2cc MD5 · raw file

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