File indexing completed on 2025-01-19 09:47:35
0001
0002
0003
0004
0005
0006 #if !defined(BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM)
0007 #define BOOST_SPIRIT_KARMA_OUTPUT_ITERATOR_MAY_26_2007_0506PM
0008
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012
0013 #include <iterator>
0014 #include <vector>
0015 #include <algorithm>
0016
0017 #include <boost/config.hpp>
0018 #include <boost/noncopyable.hpp>
0019 #include <boost/mpl/if.hpp>
0020
0021 #include <boost/spirit/home/karma/generator.hpp>
0022 #include <boost/spirit/home/support/iterators/ostream_iterator.hpp>
0023 #include <boost/spirit/home/support/unused.hpp>
0024
0025 #if defined(BOOST_MSVC) && defined(BOOST_SPIRIT_UNICODE)
0026 #include <boost/spirit/home/support/char_encoding/unicode.hpp>
0027 #endif
0028
0029 namespace boost { namespace spirit { namespace karma { namespace detail
0030 {
0031
0032
0033
0034 class position_sink
0035 {
0036 public:
0037 position_sink() : count(0), line(1), column(1) {}
0038 void tidy() { count = 0; line = 1; column = 1; }
0039
0040 template <typename T>
0041 void output(T const& value)
0042 {
0043 ++count;
0044 if (value == '\n') {
0045 ++line;
0046 column = 1;
0047 }
0048 else {
0049 ++column;
0050 }
0051 }
0052 std::size_t get_count() const { return count; }
0053 std::size_t get_line() const { return line; }
0054 std::size_t get_column() const { return column; }
0055
0056 private:
0057 std::size_t count;
0058 std::size_t line;
0059 std::size_t column;
0060 };
0061
0062
0063 struct position_policy
0064 {
0065 position_policy() {}
0066 position_policy(position_policy const& rhs)
0067 : track_position_data(rhs.track_position_data) {}
0068
0069 template <typename T>
0070 void output(T const& value)
0071 {
0072
0073 track_position_data.output(value);
0074 }
0075
0076
0077 std::size_t get_out_count() const
0078 {
0079 return track_position_data.get_count();
0080 }
0081
0082
0083 std::size_t get_line() const
0084 {
0085 return track_position_data.get_line();
0086 }
0087
0088
0089 std::size_t get_column() const
0090 {
0091 return track_position_data.get_column();
0092 }
0093
0094 private:
0095 position_sink track_position_data;
0096 };
0097
0098 struct no_position_policy
0099 {
0100 no_position_policy() {}
0101 no_position_policy(no_position_policy const&) {}
0102
0103 template <typename T>
0104 void output(T const& ) {}
0105 };
0106
0107
0108
0109
0110
0111 template <typename OutputIterator>
0112 class counting_sink : boost::noncopyable
0113 {
0114 public:
0115 counting_sink(OutputIterator& sink_, std::size_t count_ = 0
0116 , bool enabled = true)
0117 : count(count_), initial_count(count), prev_count(0), sink(sink_)
0118 {
0119 prev_count = sink.chain_counting(enabled ? this : NULL);
0120 }
0121 ~counting_sink()
0122 {
0123 if (prev_count)
0124 prev_count->update_count(count-initial_count);
0125 sink.chain_counting(prev_count);
0126 }
0127
0128 void output()
0129 {
0130 ++count;
0131 }
0132 std::size_t get_count() const { return count; }
0133
0134
0135 void update_count(std::size_t c)
0136 {
0137 count += c;
0138 }
0139
0140 private:
0141 std::size_t count;
0142 std::size_t initial_count;
0143 counting_sink* prev_count;
0144 OutputIterator& sink;
0145 };
0146
0147
0148 template <typename OutputIterator>
0149 struct counting_policy
0150 {
0151 public:
0152 counting_policy() : count(NULL) {}
0153 counting_policy(counting_policy const& rhs) : count(rhs.count) {}
0154
0155
0156 counting_sink<OutputIterator>* chain_counting(
0157 counting_sink<OutputIterator>* count_data)
0158 {
0159 counting_sink<OutputIterator>* prev_count = count;
0160 count = count_data;
0161 return prev_count;
0162 }
0163
0164 template <typename T>
0165 void output(T const&)
0166 {
0167
0168 if (NULL != count)
0169 count->output();
0170 }
0171
0172 private:
0173 counting_sink<OutputIterator>* count;
0174 };
0175
0176 struct no_counting_policy
0177 {
0178 no_counting_policy() {}
0179 no_counting_policy(no_counting_policy const&) {}
0180
0181 template <typename T>
0182 void output(T const& ) {}
0183 };
0184
0185
0186
0187
0188
0189 class buffer_sink : boost::noncopyable
0190 {
0191
0192
0193
0194 #if (defined(_MSC_VER) || defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) && defined(BOOST_SPIRIT_UNICODE)
0195 typedef spirit::char_encoding::unicode::char_type buffer_char_type;
0196 #else
0197 typedef wchar_t buffer_char_type;
0198 #endif
0199
0200 public:
0201 buffer_sink()
0202 : width(0) {}
0203
0204 ~buffer_sink()
0205 {
0206 tidy();
0207 }
0208
0209 void enable(std::size_t width_)
0210 {
0211 tidy();
0212 width = (width_ == std::size_t(-1)) ? 0 : width_;
0213 buffer.reserve(width);
0214 }
0215
0216 void tidy()
0217 {
0218 buffer.clear();
0219 width = 0;
0220 }
0221
0222 template <typename T>
0223 void output(T const& value)
0224 {
0225 BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(buffer_char_type));
0226 buffer.push_back(value);
0227 }
0228
0229 template <typename OutputIterator_>
0230 bool copy(OutputIterator_& sink, std::size_t maxwidth) const
0231 {
0232 #if defined(BOOST_MSVC)
0233 #pragma warning(push)
0234 #pragma warning(disable: 4267)
0235 #endif
0236 typename std::basic_string<buffer_char_type>::const_iterator end =
0237 buffer.begin() + (std::min)(buffer.size(), maxwidth);
0238
0239 #if defined(BOOST_MSVC)
0240 #pragma warning(disable: 4244)
0241 #endif
0242 std::copy(buffer.begin(), end, sink);
0243 #if defined(BOOST_MSVC)
0244 #pragma warning(pop)
0245 #endif
0246 return true;
0247 }
0248 template <typename RestIterator>
0249 bool copy_rest(RestIterator& sink, std::size_t start_at) const
0250 {
0251 #if defined(BOOST_MSVC)
0252 #pragma warning(push)
0253 #pragma warning(disable: 4267)
0254 #endif
0255 typename std::basic_string<buffer_char_type>::const_iterator begin =
0256 buffer.begin() + (std::min)(buffer.size(), start_at);
0257
0258 #if defined(BOOST_MSVC)
0259 #pragma warning(disable: 4244)
0260 #endif
0261 std::copy(begin, buffer.end(), sink);
0262 #if defined(BOOST_MSVC)
0263 #pragma warning(pop)
0264 #endif
0265 return true;
0266 }
0267
0268 std::size_t buffer_size() const
0269 {
0270 return buffer.size();
0271 }
0272
0273 private:
0274 std::size_t width;
0275 std::basic_string<buffer_char_type> buffer;
0276 };
0277
0278
0279 struct buffering_policy
0280 {
0281 public:
0282 buffering_policy() : buffer(NULL) {}
0283 buffering_policy(buffering_policy const& rhs) : buffer(rhs.buffer) {}
0284
0285
0286 buffer_sink* chain_buffering(buffer_sink* buffer_data)
0287 {
0288 buffer_sink* prev_buffer = buffer;
0289 buffer = buffer_data;
0290 return prev_buffer;
0291 }
0292
0293 template <typename T>
0294 bool output(T const& value)
0295 {
0296
0297 if (NULL != buffer) {
0298 buffer->output(value);
0299 return false;
0300 }
0301 return true;
0302 }
0303
0304 bool has_buffer() const { return NULL != buffer; }
0305
0306 private:
0307 buffer_sink* buffer;
0308 };
0309
0310 struct no_buffering_policy
0311 {
0312 no_buffering_policy() {}
0313 no_buffering_policy(no_buffering_policy const&) {}
0314
0315 template <typename T>
0316 bool output(T const& )
0317 {
0318 return true;
0319 }
0320
0321 bool has_buffer() const { return false; }
0322 };
0323
0324
0325
0326 template <typename OutputIterator>
0327 struct enable_buffering;
0328
0329 template <typename OutputIterator, typename Properties
0330 , typename Derived = unused_type>
0331 class output_iterator;
0332
0333
0334 template <typename Buffering, typename Counting, typename Tracking>
0335 struct output_iterator_base : Buffering, Counting, Tracking
0336 {
0337 typedef Buffering buffering_policy;
0338 typedef Counting counting_policy;
0339 typedef Tracking tracking_policy;
0340
0341 output_iterator_base() {}
0342 output_iterator_base(output_iterator_base const& rhs)
0343 : buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
0344 {}
0345
0346 template <typename T>
0347 bool output(T const& value)
0348 {
0349 this->counting_policy::output(value);
0350 this->tracking_policy::output(value);
0351 return this->buffering_policy::output(value);
0352 }
0353 };
0354
0355 template <typename Buffering, typename Counting, typename Tracking>
0356 struct disabling_output_iterator : Buffering, Counting, Tracking
0357 {
0358 typedef Buffering buffering_policy;
0359 typedef Counting counting_policy;
0360 typedef Tracking tracking_policy;
0361
0362 disabling_output_iterator() : do_output(true) {}
0363 disabling_output_iterator(disabling_output_iterator const& rhs)
0364 : buffering_policy(rhs), counting_policy(rhs), tracking_policy(rhs)
0365 , do_output(rhs.do_output)
0366 {}
0367
0368 template <typename T>
0369 bool output(T const& value)
0370 {
0371 if (!do_output)
0372 return false;
0373
0374 this->counting_policy::output(value);
0375 this->tracking_policy::output(value);
0376 return this->buffering_policy::output(value);
0377 }
0378
0379 bool do_output;
0380 };
0381
0382
0383 template <typename OutputIterator, typename Properties, typename Derived>
0384 struct make_output_iterator
0385 {
0386
0387 typedef typename mpl::if_<
0388 traits::not_is_unused<Derived>, Derived
0389 , output_iterator<OutputIterator, Properties, Derived>
0390 >::type most_derived_type;
0391
0392 static const generator_properties::enum_type properties = static_cast<generator_properties::enum_type>(Properties::value);
0393
0394 typedef typename mpl::if_c<
0395 (properties & generator_properties::tracking) ? true : false
0396 , position_policy, no_position_policy
0397 >::type tracking_type;
0398
0399 typedef typename mpl::if_c<
0400 (properties & generator_properties::buffering) ? true : false
0401 , buffering_policy, no_buffering_policy
0402 >::type buffering_type;
0403
0404 typedef typename mpl::if_c<
0405 (properties & generator_properties::counting) ? true : false
0406 , counting_policy<most_derived_type>, no_counting_policy
0407 >::type counting_type;
0408
0409 typedef typename mpl::if_c<
0410 (properties & generator_properties::disabling) ? true : false
0411 , disabling_output_iterator<buffering_type, counting_type, tracking_type>
0412 , output_iterator_base<buffering_type, counting_type, tracking_type>
0413 >::type type;
0414 };
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428 template <typename OutputIterator, typename Properties, typename Derived>
0429 class output_iterator
0430 : public make_output_iterator<OutputIterator, Properties, Derived>::type
0431 {
0432 private:
0433
0434 typedef typename make_output_iterator<
0435 OutputIterator, Properties, Derived>::type base_iterator;
0436
0437 public:
0438 typedef std::output_iterator_tag iterator_category;
0439 typedef void value_type;
0440 typedef void difference_type;
0441 typedef void pointer;
0442 typedef void reference;
0443
0444 explicit output_iterator(OutputIterator& sink_)
0445 : sink(&sink_)
0446 {}
0447 output_iterator(output_iterator const& rhs)
0448 : base_iterator(rhs), sink(rhs.sink)
0449 {}
0450
0451 output_iterator& operator*() { return *this; }
0452 output_iterator& operator++()
0453 {
0454 if (!this->base_iterator::has_buffer())
0455 ++(*sink);
0456 return *this;
0457 }
0458 output_iterator operator++(int)
0459 {
0460 if (!this->base_iterator::has_buffer()) {
0461 output_iterator t(*this);
0462 ++(*sink);
0463 return t;
0464 }
0465 return *this;
0466 }
0467
0468 #if defined(BOOST_MSVC)
0469
0470 #pragma warning (push)
0471 #pragma warning (disable: 4244)
0472 #endif
0473 template <typename T>
0474 void operator=(T const& value)
0475 {
0476 if (this->base_iterator::output(value))
0477 *(*sink) = value;
0478 }
0479 #if defined(BOOST_MSVC)
0480 #pragma warning (pop)
0481 #endif
0482
0483
0484 bool good() const { return true; }
0485
0486
0487 OutputIterator& base() { return *sink; }
0488
0489 protected:
0490
0491 OutputIterator* sink;
0492 };
0493
0494
0495 template <typename T, typename Elem, typename Traits, typename Properties>
0496 class output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
0497 : public output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
0498 , output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties> >
0499 {
0500 private:
0501 typedef output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties
0502 , output_iterator<karma::ostream_iterator<T, Elem, Traits>, Properties>
0503 > base_type;
0504 typedef karma::ostream_iterator<T, Elem, Traits> base_iterator_type;
0505 typedef std::basic_ostream<Elem, Traits> ostream_type;
0506
0507 public:
0508 output_iterator(base_iterator_type& sink)
0509 : base_type(sink) {}
0510
0511 ostream_type& get_ostream() { return (*this->sink).get_ostream(); }
0512 ostream_type const& get_ostream() const { return (*this->sink).get_ostream(); }
0513
0514
0515 bool good() const { return (*this->sink).get_ostream().good(); }
0516 };
0517
0518
0519
0520
0521
0522 template <typename OutputIterator>
0523 struct enable_counting
0524 {
0525 enable_counting(OutputIterator& sink_, std::size_t count = 0)
0526 : count_data(sink_, count) {}
0527
0528
0529 std::size_t count() const
0530 {
0531 return count_data.get_count();
0532 }
0533
0534 private:
0535 counting_sink<OutputIterator> count_data;
0536 };
0537
0538 template <typename OutputIterator>
0539 struct disable_counting
0540 {
0541 disable_counting(OutputIterator& sink_)
0542 : count_data(sink_, 0, false) {}
0543
0544 private:
0545 counting_sink<OutputIterator> count_data;
0546 };
0547
0548
0549
0550
0551
0552 template <typename OutputIterator>
0553 struct enable_buffering
0554 {
0555 enable_buffering(OutputIterator& sink_
0556 , std::size_t width = std::size_t(-1))
0557 : sink(sink_), prev_buffer(NULL), enabled(false)
0558 {
0559 buffer_data.enable(width);
0560 prev_buffer = sink.chain_buffering(&buffer_data);
0561 enabled = true;
0562 }
0563 ~enable_buffering()
0564 {
0565 disable();
0566 }
0567
0568
0569 void disable()
0570 {
0571 if (enabled) {
0572 BOOST_VERIFY(&buffer_data == sink.chain_buffering(prev_buffer));
0573 enabled = false;
0574 }
0575 }
0576
0577
0578 bool buffer_copy(std::size_t maxwidth = std::size_t(-1)
0579 , bool disable_ = true)
0580 {
0581 if (disable_)
0582 disable();
0583 return buffer_data.copy(sink, maxwidth) && sink.good();
0584 }
0585
0586
0587 std::size_t buffer_size() const
0588 {
0589 return buffer_data.buffer_size();
0590 }
0591
0592
0593 template <typename RestIterator>
0594 bool buffer_copy_rest(RestIterator& sink, std::size_t start_at = 0) const
0595 {
0596 return buffer_data.copy_rest(sink, start_at);
0597 }
0598
0599
0600 template <typename OutputIterator_>
0601 bool buffer_copy_to(OutputIterator_& sink
0602 , std::size_t maxwidth = std::size_t(-1)) const
0603 {
0604 return buffer_data.copy(sink, maxwidth);
0605 }
0606
0607 private:
0608 OutputIterator& sink;
0609 buffer_sink buffer_data;
0610 buffer_sink* prev_buffer;
0611 bool enabled;
0612 };
0613
0614
0615
0616
0617 template <typename OutputIterator>
0618 struct disable_output
0619 {
0620 disable_output(OutputIterator& sink_)
0621 : sink(sink_), prev_do_output(sink.do_output)
0622 {
0623 sink.do_output = false;
0624 }
0625 ~disable_output()
0626 {
0627 sink.do_output = prev_do_output;
0628 }
0629
0630 OutputIterator& sink;
0631 bool prev_do_output;
0632 };
0633
0634
0635 template <typename Sink>
0636 bool sink_is_good(Sink const&)
0637 {
0638 return true;
0639 }
0640
0641 template <typename OutputIterator, typename Derived>
0642 bool sink_is_good(output_iterator<OutputIterator, Derived> const& sink)
0643 {
0644 return sink.good();
0645 }
0646
0647 }}}}
0648
0649 #endif
0650