io.hh 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. #include <iosfwd>
  11. #include <sstream>
  12. namespace ra {
  13. // TODO merge with ply_ravel @ ply.hh. But should control order.
  14. template <class A>
  15. inline std::ostream &
  16. operator<<(std::ostream & o, FormatArray<A> const & fa)
  17. {
  18. // FIXME note that this copies / resets the Iterator if fa.a already is one; see [ra35].
  19. auto a = ra::start(fa.a);
  20. static_assert(size_s(a)!=DIM_BAD, "cannot print type");
  21. rank_t const rank = a.rank();
  22. auto sha = concrete(shape(a));
  23. auto ind = with_same_shape(sha, 0);
  24. if (withshape==fa.shape || (defaultshape==fa.shape && size_s(a)==DIM_ANY)) {
  25. o << start(sha) << '\n';
  26. }
  27. for (rank_t k=0; k<rank; ++k) {
  28. if (0==sha[k]) {
  29. return o;
  30. }
  31. }
  32. // order here is row-major on purpose.
  33. for (;;) {
  34. o << *(a.flat());
  35. for (int k=0; ; ++k) {
  36. if (k>=rank) {
  37. return o;
  38. } else if (ind[rank-1-k]<sha[rank-1-k]-1) {
  39. ++ind[rank-1-k];
  40. a.adv(rank-1-k, 1);
  41. switch (k) {
  42. case 0: o << fa.sep0; break;
  43. case 1: o << fa.sep1; break;
  44. default: std::fill_n(std::ostream_iterator<char const *>(o, ""), k, fa.sep2);
  45. }
  46. break;
  47. } else {
  48. ind[rank-1-k] = 0;
  49. a.adv(rank-1-k, 1-sha[rank-1-k]);
  50. }
  51. }
  52. }
  53. }
  54. // Static size.
  55. template <class C> requires (!is_scalar<C> && size_s<C>()!=DIM_ANY)
  56. inline std::istream &
  57. operator>>(std::istream & i, C & c)
  58. {
  59. for (auto & ci: c) { i >> ci; }
  60. return i;
  61. }
  62. // Special case for std::vector, to handle create-new / resize() difference.
  63. template <class T, class A>
  64. inline std::istream &
  65. operator>>(std::istream & i, std::vector<T, A> & c)
  66. {
  67. if (dim_t n; !((i >> n).fail())) {
  68. RA_CHECK(n>=0, "negative sizes in input: ", n);
  69. c.resize(n);
  70. for (auto & ci: c) { i >> ci; }
  71. }
  72. return i;
  73. }
  74. // Expr size, so read shape and possibly allocate (TODO try to avoid).
  75. template <class C> requires (size_s<C>()==DIM_ANY)
  76. inline std::istream &
  77. operator>>(std::istream & i, C & c)
  78. {
  79. if (decltype(shape(c)) s; i >> s) {
  80. std::decay_t<C> cc(s, ra::none);
  81. RA_CHECK(every(start(s)>=0), "negative sizes in input: ", s);
  82. // avoid copying in case Container's elements don't support it.
  83. swap(c, cc);
  84. // need row-major, serial iteration here. FIXME use ra:: traversal.
  85. for (auto & ci: c) { i >> ci; }
  86. }
  87. return i;
  88. }
  89. } // namespace ra