io.hh 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // -*- mode: c++; coding: utf-8 -*-
  2. // ra-ra - Write and read arrays, expressions.
  3. // (c) Daniel Llorens - 2014-2018, 2021
  4. // This library is free software; you can redistribute it and/or modify it under
  5. // the terms of the GNU Lesser General Public License as published by the Free
  6. // Software Foundation; either version 3 of the License, or (at your option) any
  7. // later version.
  8. #pragma once
  9. #include "big.hh"
  10. namespace ra {
  11. // TODO merge with ply_ravel @ ply.hh. But should control order.
  12. template <class A>
  13. inline std::ostream &
  14. operator<<(std::ostream & o, FormatArray<A> const & fa)
  15. {
  16. static_assert(!has_len<A>, "len used outside subscript context.");
  17. // FIXME note that this copies / resets the Iterator if fa.a already is one; see [ra35].
  18. auto a = ra::start(fa.a);
  19. static_assert(size_s(a)!=DIM_BAD, "cannot print type");
  20. rank_t const rank = a.rank();
  21. auto sha = concrete(shape(a));
  22. auto ind = with_same_shape(sha, 0);
  23. if (withshape==fa.shape || (defaultshape==fa.shape && size_s(a)==DIM_ANY)) {
  24. o << start(sha) << '\n';
  25. }
  26. for (rank_t k=0; k<rank; ++k) {
  27. if (0==sha[k]) {
  28. return o;
  29. }
  30. }
  31. // order here is row-major on purpose.
  32. for (;;) {
  33. o << *(a.flat());
  34. for (int k=0; ; ++k) {
  35. if (k>=rank) {
  36. return o;
  37. } else if (ind[rank-1-k]<sha[rank-1-k]-1) {
  38. ++ind[rank-1-k];
  39. a.adv(rank-1-k, 1);
  40. switch (k) {
  41. case 0: o << fa.sep0; break;
  42. case 1: o << fa.sep1; break;
  43. default: std::fill_n(std::ostream_iterator<char const *>(o, ""), k, fa.sep2);
  44. }
  45. break;
  46. } else {
  47. ind[rank-1-k] = 0;
  48. a.adv(rank-1-k, 1-sha[rank-1-k]);
  49. }
  50. }
  51. }
  52. }
  53. // Static size.
  54. template <class C> requires (!is_scalar<C> && size_s<C>()!=DIM_ANY)
  55. inline std::istream &
  56. operator>>(std::istream & i, C & c)
  57. {
  58. for (auto & ci: c) { i >> ci; }
  59. return i;
  60. }
  61. // Special case for std::vector, to handle create-new / resize() difference.
  62. template <class T, class A>
  63. inline std::istream &
  64. operator>>(std::istream & i, std::vector<T, A> & c)
  65. {
  66. if (dim_t n; !((i >> n).fail())) {
  67. RA_CHECK(n>=0, "negative sizes in input: ", n);
  68. c.resize(n);
  69. for (auto & ci: c) { i >> ci; }
  70. }
  71. return i;
  72. }
  73. // Expr size, so read shape and possibly allocate (TODO try to avoid).
  74. template <class C> requires (size_s<C>()==DIM_ANY)
  75. inline std::istream &
  76. operator>>(std::istream & i, C & c)
  77. {
  78. if (decltype(shape(c)) s; i >> s) {
  79. std::decay_t<C> cc(s, ra::none);
  80. RA_CHECK(every(start(s)>=0), "negative sizes in input: ", s);
  81. // avoid copying in case Container's elements don't support it.
  82. swap(c, cc);
  83. // need row-major, serial iteration here. FIXME use ra:: traversal.
  84. for (auto & ci: c) { i >> ci; }
  85. }
  86. return i;
  87. }
  88. } // namespace ra