Guest User

Range I/O sample

a guest
Sep 30th, 2014
214
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. */
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×