io.H 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // -*- mode: c++; coding: utf-8 -*-
  2. /// @file io.H
  3. /// @brief Write and read arrays, expressions.
  4. // (c) Daniel Llorens - 2014-2018
  5. // This library is free software; you can redistribute it and/or modify it under
  6. // the terms of the GNU Lesser General Public License as published by the Free
  7. // Software Foundation; either version 3 of the License, or (at your option) any
  8. // later version.
  9. #pragma once
  10. #include "ra/atom.H"
  11. #include "ra/format.H"
  12. #include "ra/concrete.H"
  13. #include <iosfwd>
  14. #include <sstream>
  15. #if defined(RA_CHECK_BOUNDS) && RA_CHECK_BOUNDS==0
  16. #define CHECK_BOUNDS( cond )
  17. #else
  18. #define CHECK_BOUNDS( cond ) RA_ASSERT( cond, 0 )
  19. #endif
  20. namespace ra {
  21. // TODO merge with ply_ravel @ ply.H, but should control order.
  22. // TODO custom spacers at turn of dimension.
  23. // is_foreign_vector is included b/c std::vector or std::array may be used as the type of shape().
  24. template <class A> inline
  25. std::ostream & operator<<(std::ostream & o, FormatArray<A> const & fa)
  26. {
  27. // FIXME note that this copies / resets the ArrayIterator if fa.a already is one; see [ra35].
  28. auto a = ra::start(fa.a);
  29. static_assert(size_s(a)!=DIM_BAD, "cannot print type");
  30. rank_t const rank = a.rank();
  31. auto sha = concrete(shape(a));
  32. auto ind = with_same_shape(sha, 0);
  33. if (withshape==fa.shape || (defaultshape==fa.shape && size_s(a)==DIM_ANY)) {
  34. o << start(sha) << '\n';
  35. }
  36. for (rank_t k=0; k<rank; ++k) {
  37. if (sha[k]==0) {
  38. return o;
  39. }
  40. }
  41. // unlike in ply_index(), order here is row-major on purpose.
  42. for (;;) {
  43. next: ;
  44. o << a.at(ind);
  45. for (int k=0; k<rank; ++k) {
  46. if (++ind[rank-1-k]<sha[rank-1-k]) {
  47. switch (k) {
  48. case 0: o << fa.sep0; break;
  49. case 1: o << fa.sep1; break;
  50. default: std::fill_n(std::ostream_iterator<char const *>(o, ""), k, fa.sep2);
  51. }
  52. goto next;
  53. } else {
  54. ind[rank-1-k] = 0;
  55. }
  56. }
  57. return o;
  58. }
  59. }
  60. template <class A> inline
  61. std::enable_if_t<is_ra<A> || is_foreign_vector<A>, std::ostream &>
  62. operator<<(std::ostream & o, A && a)
  63. {
  64. return o << format_array(a);
  65. }
  66. // initializer_list cannot match A && above.
  67. template <class T> inline
  68. std::ostream & operator<<(std::ostream & o, std::initializer_list<T> const & a)
  69. {
  70. return o << format_array(a);
  71. }
  72. // Static size.
  73. template <class C> inline
  74. std::enable_if_t<!is_scalar<C> && size_s<C>()!=DIM_ANY, std::istream &>
  75. operator>>(std::istream & i, C & c)
  76. {
  77. for (auto & ci: c) { i >> ci; }
  78. return i;
  79. }
  80. // Special case for std::vector, to handle create-new / resize() difference.
  81. template <class T, class A> inline
  82. std::istream &
  83. operator>>(std::istream & i, std::vector<T, A> & c)
  84. {
  85. if (dim_t n; !((i >> n).fail())) {
  86. CHECK_BOUNDS(n>=0 && "negative sizes in input");
  87. c.resize(n);
  88. for (auto & ci: c) { i >> ci; }
  89. }
  90. return i;
  91. }
  92. // Expr size, so read shape and possibly allocate (TODO try to avoid).
  93. template <class C> inline
  94. std::enable_if_t<size_s<C>()==DIM_ANY, std::istream &>
  95. operator>>(std::istream & i, C & c)
  96. {
  97. if (decltype(shape(c)) s; i >> s) {
  98. std::decay_t<C> cc(s, ra::none);
  99. CHECK_BOUNDS(every(start(s)>=0) && "negative sizes in input");
  100. // avoid copying in case Container's elements don't support it.
  101. swap(c, cc);
  102. // need row-major, serial iteration here. FIXME use ra:: traversal.
  103. for (auto & ci: c) { i >> ci; }
  104. }
  105. return i;
  106. }
  107. } // namespace ra
  108. #undef CHECK_BOUNDS