Advertisement
Guest User

Range I/O sample

a guest
Sep 30th, 2014
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.01 KB | None | 0 0
  1. #include <cstddef>
  2. #include <iomanip>
  3. #include <iostream>
  4. #include <list>
  5. #include <map>
  6. #include <set>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10.  
  11. #include <boost/iterator/iterator_adaptor.hpp>
  12. #include <boost/range.hpp>
  13. #include <boost/range/adaptor/argument_fwd.hpp>
  14. #include <boost/tuple/tuple.hpp>
  15. #include <boost/tuple/tuple_io.hpp>
  16. #include <boost/units/quantity.hpp>
  17. #include <boost/units/systems/si.hpp>
  18. #include <boost/units/systems/si/io.hpp>
  19.  
  20. #include "measurement.hpp"  // An uncertain type called measure.
  21.  
  22. #include "rangeio" // (I'm reusing the version of range I/O already written for the std proposal)
  23. using std::write_all;
  24.  
  25. // BEGIN stuff needed for column separator /////////////////////////////////////
  26. /*
  27.  * This is all for a special delimiter that adds a new line after a column is filled.
  28.  */
  29. template <typename Delimiter>
  30. struct column_separator_printer_t
  31. {
  32.   column_separator_printer_t(Delimiter&& d, std::size_t n) :
  33.     d_{std::forward<Delimiter>(d)}, colcount_{n}, i_{0}
  34.   {}
  35.  
  36.   Delimiter&& d_;
  37.   std::size_t const colcount_;
  38.   mutable std::size_t i_;
  39. };
  40.  
  41. template <typename Delimiter, typename CharT, typename Traits>
  42. auto operator<<(std::basic_ostream<CharT, Traits>& o, column_separator_printer_t<Delimiter> const& c) ->
  43.   std::basic_ostream<CharT, Traits>&
  44. {
  45.   o << c.d_;
  46.   if (++c.i_ == c.colcount_)
  47.   {
  48.     o << '\n';
  49.     c.i_ = 0;
  50.   }
  51.   return o;
  52. }
  53.  
  54. template <typename Delimiter>
  55. auto column_sep(Delimiter&& d, std::size_t n)
  56. {
  57.   return column_separator_printer_t<Delimiter>{std::forward<Delimiter>(d), n};
  58. }
  59. // END stuff needed for column separator ///////////////////////////////////////
  60.  
  61. // BEGIN stuff needed for column major ordering ////////////////////////////////
  62. /*
  63.  * This is all for a range adaptor that reorders the elements in a range into column-major order.
  64.  */
  65. template <typename ForwardIterator>
  66. struct column_major_order_iterator :
  67.   boost::iterator_adaptor<column_major_order_iterator<ForwardIterator>, ForwardIterator>
  68. {
  69.   column_major_order_iterator() = default;
  70.   column_major_order_iterator(ForwardIterator i, ForwardIterator b, ForwardIterator e, std::size_t c) :
  71.     boost::iterator_adaptor<column_major_order_iterator<ForwardIterator>, ForwardIterator>{i},
  72.     begin_{b}, end_{e}, row_current_{b}
  73.   {
  74.     auto const num_elements = std::size_t(std::distance(begin_, end_));
  75.     stride_ = (num_elements / c) + ((num_elements % c) ? 1 : 0);
  76.   }
  77.  
  78.   void increment()
  79.   {
  80.     auto& i = this->base_reference();
  81.    
  82.     auto const d = std::size_t(std::distance(i, end_));
  83.     auto const row_end = std::next(begin_, stride_);
  84.     if (d > stride_)
  85.       std::advance(i, stride_);
  86.     else if ((row_current_ != row_end) && (++row_current_ != row_end))
  87.       i = row_current_;
  88.     else
  89.       i = end_;
  90.   }
  91.  
  92.   ForwardIterator  begin_;
  93.   ForwardIterator  end_;
  94.   ForwardIterator  row_current_;
  95.   std::size_t  stride_;
  96. };
  97.  
  98. template <typename Range>
  99. struct column_major_order_range :
  100.   boost::iterator_range<column_major_order_iterator<typename boost::range_iterator<Range>::type>>
  101. {
  102.   column_major_order_range(Range& r, std::size_t colcount) :
  103.     boost::iterator_range<column_major_order_iterator<typename boost::range_iterator<Range>::type>>{
  104.       column_major_order_iterator<typename boost::range_iterator<Range>::type>{boost::begin(r), boost::begin(r), boost::end(r), colcount},
  105.       column_major_order_iterator<typename boost::range_iterator<Range>::type>{boost::end(r), boost::begin(r), boost::end(r), colcount}
  106.     }
  107.   {}
  108. };
  109.  
  110. template <typename T>
  111. struct column_major_order_holder : boost::range_detail::holder<std::size_t>
  112. {
  113.   column_major_order_holder(T colcount) :
  114.     boost::range_detail::holder<std::size_t>{std::size_t(colcount)}
  115.   {}
  116. };
  117.  
  118. static auto column_major_ordered = boost::range_detail::forwarder<column_major_order_holder>();
  119.  
  120. template <typename ForwardRange, typename T>
  121. inline auto operator|(ForwardRange& r, column_major_order_holder<T> const& f)
  122. {
  123.   return column_major_order_range<ForwardRange>(r, f.val);
  124. }
  125.  
  126. template <typename ForwardRange, typename T>
  127. inline auto operator|(ForwardRange const& r, column_major_order_holder<T> const& f)
  128. {
  129.   return column_major_order_range<ForwardRange const>(r, f.val);
  130. }
  131.  
  132. /*
  133.  * This is all for a special delimiter that adds new lines to print the elements in columns,
  134.  * filling up the columns before the rows.
  135.  */
  136. template <typename Delimiter>
  137. struct column_major_separator_printer_t
  138. {
  139.   column_major_separator_printer_t(Delimiter&& d, std::size_t total, std::size_t colcount) :
  140.     d_{std::forward<Delimiter>(d)}, total_{total}, colcount_{colcount},
  141.     full_rows_{(total / colcount) + ((total % colcount) ? 1 : 0) - (total % colcount)},
  142.     i_{0}
  143.   {}
  144.  
  145.   Delimiter&& d_;
  146.   std::size_t const total_;
  147.   std::size_t const colcount_;
  148.   std::size_t const full_rows_;
  149.   mutable std::size_t i_;
  150. };
  151.  
  152. template <typename Delimiter, typename CharT, typename Traits>
  153. auto operator<<(std::basic_ostream<CharT, Traits>& o, column_major_separator_printer_t<Delimiter> const& c) ->
  154.   std::basic_ostream<CharT, Traits>&
  155. {
  156.   o << c.d_;
  157.  
  158.   if (++c.i_ <= (c.full_rows_ * c.colcount_))
  159.   {
  160.     if ((c.i_ % c.colcount_) == 0)
  161.       o << '\n';
  162.   }
  163.   else
  164.   {
  165.     auto const i = c.i_ - (c.full_rows_ * c.colcount_);
  166.     if ((i % (c.colcount_ - 1)) == 0)
  167.       o << '\n';
  168.   }
  169.  
  170.   return o;
  171. }
  172.  
  173. template <typename Range, typename Delimiter>
  174. auto column_major_sep(Range const& r, Delimiter&& d, std::size_t n)
  175. {
  176.   using std::begin;
  177.   using std::end;
  178.  
  179.   return column_major_separator_printer_t<Delimiter>{std::forward<Delimiter>(d), std::size_t(std::distance(begin(r), end(r))), n};
  180. }
  181. // END stuff needed for column major ordering //////////////////////////////////
  182.  
  183. // Not generally a great idea, but it was in the original code, so...
  184. namespace std {
  185.  
  186. template <typename T1, typename T2, typename CharT, typename Traits>
  187. auto operator<<(std::basic_ostream<CharT, Traits>& o, std::pair<T1, T2> const& p) ->
  188.   std::basic_ostream<CharT, Traits>&
  189. {
  190.   return o << p.first << ' ' << p.second;
  191. }
  192.  
  193. } // namespace std
  194.  
  195. auto main() -> int
  196. {
  197.   using namespace boost::units;
  198.   using namespace boost::units::si;
  199.  
  200.   int test[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  201.   double testd[] = { 1., 2., 3., 4., 5., 6., 7., 8., 9., 10. };
  202.  
  203.   // Note: the original code creates a separator_printer named p1, then reuses
  204.   // it over and over. I didn't do that - I used multiple calls to write_all,
  205.   // so the delimiter has to be repeated.
  206.   // If you want to avoid repeating the delimiter, then you can do:
  207.   //   auto p1 = [](auto const& r) { return write_all(r, ",  "); };
  208.   // (possibly with a universal reference and std::forward). Then replace all:
  209.   //   std::cout << write_all(XXX, ",  ") << '\n';
  210.   // with:
  211.   //   std::cout << p1(XXX) << '\n';
  212.   // and so on.
  213.  
  214.   std::cout << write_all(test, ",  ") << '\n'; // 1,2,3,4,5,6,7,8,9,10
  215.  
  216.   // This is the version with the automatic newline... which is unnecessary now because it's all one statement.
  217.   // If you really want an automatic newline, you can wrap write_all in a lambda that appends it.
  218.   std::cout << write_all(test, ",  ") << "|\n"; // 1,2,3,4,5,6,7,8,9,10|
  219.  
  220.   // If you need to reuse the prefix/suffix/delimiter combo, you could easily make a lambda
  221.   std::cout << "int[10] = {" << write_all(test, ",  ") << "};\n"; // int[10] = {1,  2,  3,  4,  5,  6,  7,  8,  9,  10};
  222.  
  223.   std::cout << write_all(test, "___") << '\n'; // 1___2___3___4___5___6___7___8___9___10
  224.  
  225.   std::cout << write_all(testd, ",  ") << '\n'; // 1,2,3,4,5,6,7,8,9,10
  226.  
  227.   std::cout.precision(5);
  228.   std::cout << std::showpos << std::showpoint << '\n';
  229.  
  230.   std::cout << write_all(testd, ",  ") << '\n'; // +1.0000,+2.0000,+3.0000,+4.0000,+5.0000,+6.0000,+7.0000,+8.0000,+9.0000,+10.000
  231.   std::cout << std::noshowpos << '\n'; // Switch off fancy +.
  232.  
  233.   // NOTE: When I ran the original program, i didn't get the expected output - everything was in metres; units weren't scaled.
  234.   // This code *does* scale the units.
  235.   quantity<length> testq[] = {2345.6 * meters, 123.4 * meters, 0.0123 * meters};
  236.   std::cout << engineering_prefix << write_all(testq, ",  ") << '\n'; // 2.3456 km,  123.40 m,  12.300 mm
  237.  
  238.   // Again, the units weren't scaled in the original code. I didn't scale them here.
  239.   quantity<length, measurement<double> > testqu[] = {measurement<double>(45210.0, 1234.0) * meters, measurement<double>(789, 2.5) * meters, measurement<double>(0.000567,2.34e-5) * meters};
  240.   std::cout << write_all(testqu, ",  ") << '\n'; // 45210.(+/-1234.0) m,  789.00(+/-2.5000) m,  0.00056700(+/-2.3400e-05) m
  241.  
  242.   const char* testCstring[] = {"one", "two", "three", "four","five", "six","seven","eight", "nine", "ten"};
  243.   std::cout << write_all(testCstring, ",  ") << '\n'; // Type is now a C string.
  244.  
  245.   std::string teststring[] = {"ONE", "TWO", "THREE", "FOUR","FIVE", "SIX","SEVEN","EIGHT", "NINE", "TEN"};
  246.   std::cout << write_all(teststring, ",  ") << '\n'; // Type is now a std::string.
  247.  
  248.   // Now some other sequence printers.
  249.  
  250.   // Requires some extra code (~30 lines, see above main())
  251.   std::cout << write_all(test, column_sep(',', 4)) << '\n'; // 1,2,3,4, and then  5,6,7,8, and then 9,10
  252.  
  253.   // Requires some extra code (~100 lines see above main())
  254.   std::cout << std::setw(16) << write_all(test | column_major_ordered(4), column_major_sep(test, "", 4)) << '\n' << '\n'; // 1 4 7 10 then 2 5 8, then 3 6 9
  255.  
  256.   std::vector<double> testv(testd, testd + sizeof(testd)/ sizeof(testd[0]));
  257.   std::cout << write_all(testv, ",  ") << '\n'; //   1.0000,  2.0000,  3.0000,  4.0000,  5.0000,  6.0000,  7.0000,  8.0000,  9.0000,  10.000
  258.  
  259.   std::list<double> testl(testd, testd + sizeof(testd)/ sizeof(testd[0]));
  260.   std::cout << write_all(testl, column_sep(",", 4)) << '\n'; // 1.0000,2.0000,3.0000,4.0000,
  261.                                                              // 5.0000,6.0000,7.0000,8.0000,
  262.                                                              // 7.0000
  263.  
  264.   std::set<double> tests;
  265.   tests.insert(3.);
  266.   tests.insert(4.);
  267.   tests.insert(5.);
  268.   tests.insert(6.);
  269.   tests.insert(7.);
  270.   std::cout << write_all(tests, column_sep(",", 4)) << '\n'; // 3.0000,4.0000,5.0000,6.0000,
  271.                                                              // 7.0000
  272.   std::cout << std::noshowpoint;
  273.  
  274.   std::map<int, double> my_map;
  275.   my_map.insert(std::make_pair(1, 9.9));
  276.   my_map.insert(std::make_pair(2, 8.8));
  277.   my_map.insert(std::make_pair(3, 7.7));
  278.   my_map.insert(std::make_pair(4, 6.6));
  279.  
  280.   std::cout << write_all(my_map, column_sep(",", 4)) << '\n' << '\n'; //  1, 9.9,2, 8.8,3, 7.7,4, 6.6
  281.  
  282.   using boost::tuples::tuple;
  283.   using boost::tuples::make_tuple;
  284.  
  285.   tuple<int, double, std::string> ids1(23, 99.9, "my_string");  // Construct a tuple.
  286.   // But convenient to use a typedef for the tuple type.
  287.   typedef tuple<int, double, std::string> my_tuple_t;
  288.  
  289.   my_tuple_t ids2(42, 3.1459, "other_string");  // Construct another using typedef.
  290.   std::vector<my_tuple_t> testtup;
  291.   testtup.push_back(ids1);
  292.   testtup.push_back(ids2);
  293.   my_tuple_t ids3(43, 2.8, "third_string");  // Construct yet another also using typedef.
  294.   testtup.push_back(ids3);
  295.  
  296.   std::cout << write_all(testtup, column_sep(",", 4)) << '\n' << '\n'; //   (23 99.900 my_string),(42 3.1459 other_string)
  297.  
  298.   using boost::tuples::set_open;
  299.   using boost::tuples::set_delimiter;
  300.   using boost::tuples::set_close;
  301.  
  302.   std::cout << set_open('[')  << set_delimiter('_') << set_close(']') <<
  303.     "= {" << write_all(testtup, ",  ") << "};\n";
  304.   //   = {[23_99.900_my_string],  [42_3.1459_other_string],  [43_2.8000_third_string]};
  305.  
  306.   std::cout << "= {" << write_all(testtup, ",\n  ") << "};\n";
  307.   // = {[23_99.900_my_string],
  308.   //   [42_3.1459_other_string],
  309.   //   [43_2.8000_third_string]};
  310. }
  311.  
  312. /*
  313. Output:
  314.  
  315.   1,  2,  3,  4,  5,  6,  7,  8,  9,  10
  316.   1,  2,  3,  4,  5,  6,  7,  8,  9,  10|
  317.   int[10] = {1,  2,  3,  4,  5,  6,  7,  8,  9,  10};
  318.   1___2___3___4___5___6___7___8___9___10
  319.   1,  2,  3,  4,  5,  6,  7,  8,  9,  10
  320.  
  321.   +1.0000,  +2.0000,  +3.0000,  +4.0000,  +5.0000,  +6.0000,  +7.0000,  +8.0000,  +9.0000,  +10.000
  322.  
  323.   2.3456 km,  123.40 m,  12.300 mm
  324.   45210.(+/-1234.0) m,  789.00(+/-2.5000) m,  0.00056700(+/-2.3400e-05) m
  325.   one,  two,  three,  four,  five,  six,  seven,  eight,  nine,  ten
  326.   ONE,  TWO,  THREE,  FOUR,  FIVE,  SIX,  SEVEN,  EIGHT,  NINE,  TEN
  327.   1,2,3,4,
  328.   5,6,7,8,
  329.   9,10
  330.                  1               4               7              10
  331.                  2               5               8
  332.                  3               6               9
  333.  
  334.   1.0000,  2.0000,  3.0000,  4.0000,  5.0000,  6.0000,  7.0000,  8.0000,  9.0000,  10.000
  335.   1.0000,2.0000,3.0000,4.0000,
  336.   5.0000,6.0000,7.0000,8.0000,
  337.   9.0000,10.000
  338.   3.0000,4.0000,5.0000,6.0000,
  339.   7.0000
  340.   1 9.9,2 8.8,3 7.7,4 6.6
  341.  
  342.   (23 99.9 my_string),(42 3.1459 other_string),(43 2.8 third_string)
  343.  
  344.   = {[23_99.9_my_string],  [42_3.1459_other_string],  [43_2.8_third_string]};
  345.   = {[23_99.9_my_string],
  346.     [42_3.1459_other_string],
  347.     [43_2.8_third_string]};
  348. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement