HiPipe  0.7.0
C++17 data pipeline with Python bindings.
unpack.hpp
1 /****************************************************************************
2  * hipipe library
3  * Copyright (c) 2017, Cognexa Solutions s.r.o.
4  * Copyright (c) 2018, Iterait a.s.
5  * Author(s) Filip Matzner
6  *
7  * This file is distributed under the MIT License.
8  * See the accompanying file LICENSE.txt for the complete license agreement.
9  ****************************************************************************/
10 
11 #pragma once
12 
13 #include <hipipe/core/stream/stream_t.hpp>
14 #include <hipipe/core/stream/template_arguments.hpp>
15 #include <hipipe/core/utility/ndim.hpp>
16 #include <hipipe/core/utility/tuple.hpp>
17 
18 #include <range/v3/view/move.hpp>
19 #include <range/v3/view/transform.hpp>
20 
21 namespace hipipe::stream {
22 
23 namespace rgv = ranges::views;
24 
25 namespace detail {
26 
27 
28  template<std::size_t Dim, bool OnlyOne, typename... FromColumns>
29  struct unpack_impl
30  {
31  template<typename Rng>
32  static auto unpack_columns(Rng&& rng)
33  {
34  return rgv::transform(std::forward<Rng>(rng), [](batch_t source)
35  -> std::tuple<typename FromColumns::data_type...> {
36  return {std::move(source.extract<FromColumns>())...};
37  });
38  }
39 
40  template<typename Rng>
41  static
42  std::tuple<std::vector<utility::ndim_type_t<typename FromColumns::data_type, Dim>>...>
43  impl(Rng&& range_of_batches)
44  {
45  static_assert(std::is_same_v<std::decay_t<ranges::range_value_t<Rng>>, batch_t>,
46  "hipipe::stream::unpack requires a range of batches as input.");
47  static_assert(((Dim <= utility::ndims<typename FromColumns::data_type>::value) && ...),
48  "hipipe::stream::unpack requires the requested dimension to be less or equal to the"
49  " dimension of all the unpacked columns.");
50  auto raw_range_of_tuples = unpack_columns(std::forward<Rng>(range_of_batches));
51  auto tuple_of_batches = utility::unzip(std::move(raw_range_of_tuples));
52  // flatten the values in each column upto the given dimension
53  return utility::tuple_transform(std::move(tuple_of_batches), [](auto&& batch_range) {
54  // make sure to convert the flat view to std::vector to avoid dangling ref
55  return rgv::move(utility::flat_view<Dim+1>(batch_range));
56  });
57  }
58  };
59 
60  // if only a single column is unpacked, do not return a tuple
61  template<std::size_t Dim, typename FromColumn>
62  struct unpack_impl<Dim, true, FromColumn>
63  {
64  template<typename Rng>
65  static
66  std::vector<utility::ndim_type_t<typename FromColumn::data_type, Dim>>
67  impl(Rng&& range_of_tuples)
68  {
69  return std::get<0>(
70  unpack_impl<Dim, false, FromColumn>::impl(std::forward<Rng>(range_of_tuples)));
71  }
72  };
73 
74 } // namespace detail
75 
76 
108 template<typename Rng, typename... FromColumns, int Dim = 1>
109 auto
110 // The return type is actually the following, but GCC won't handle it.
111 // utility::maybe_tuple<std::vector<utility::ndim_type_t<typename FromColumns::data_type, Dim>>...>
112 unpack(Rng&& rng, from_t<FromColumns...> f, dim_t<Dim> d = dim_t<1>{})
113 {
114  return detail::unpack_impl<Dim, (sizeof...(FromColumns)==1), FromColumns...>::impl(
115  std::forward<Rng>(rng));
116 }
117 
118 } // end namespace hipipe::stream
hipipe::utility::tuple_transform
constexpr auto tuple_transform(Tuple &&tuple, Fun &&fun)
Transform each element of a tuple.
Definition: tuple.hpp:153
hipipe::stream::unpack
auto unpack(Rng &&rng, from_t< FromColumns... > f, dim_t< Dim > d=dim_t< 1 >{})
Unpack a stream into a tuple of ranges.
Definition: unpack.hpp:118
hipipe::stream::transform
auto transform(from_t< FromColumns... > f, to_t< ToColumns... > t, Fun fun, dim_t< Dim > d=dim_t< 1 >{})
Transform a subset of hipipe columns to a different subset of hipipe columns.
Definition: transform.hpp:218