HiPipe  0.6.0
C++17 data pipeline with Python bindings.
create.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/utility/tuple.hpp>
15 
16 #include <range/v3/view/transform.hpp>
17 #include <range/v3/view/chunk.hpp>
18 
19 #include <typeinfo>
20 #include <unordered_map>
21 
22 namespace hipipe::stream {
23 
24 namespace detail {
25 
26  template<typename... Columns>
27  struct create_impl {
28 
29  template<typename Source>
30  batch_t operator()(Source&& source) const
31  {
32  batch_t batch;
33 
34  if constexpr(sizeof...(Columns) == 0) {
35  static_assert("hipipe::stream::create: At least one column has to be provided.");
36  } else if constexpr(sizeof...(Columns) == 1) {
37  static_assert(std::is_constructible_v<Columns..., Source&&>,
38  "hipipe::stream::create: "
39  "Cannot convert the given data range to the selected column type.");
40  batch.insert_or_assign<Columns...>(std::forward<Source>(source));
41  } else {
42  using SourceValue = ranges::range_value_type_t<Source>;
43  static_assert(std::is_constructible_v<
44  std::tuple<typename Columns::example_type...>, SourceValue&&>,
45  "hipipe::stream::create: "
46  "Cannot convert the given data range to the selected column types.");
47  std::tuple<Columns...> data = utility::unzip(std::forward<Source>(source));
48  utility::tuple_for_each(data, [&batch](auto& column){
49  batch.insert_or_assign<std::decay_t<decltype(column)>>(std::move(column));
50  });
51  }
52 
53  return batch;
54  }
55  };
56 
57  template<typename... Columns>
58  class create_fn {
59  private:
60  friend ranges::view::view_access;
61 
62  static auto bind(create_fn<Columns...> fun, std::size_t batch_size = 1)
63  {
64  return ranges::make_pipeable(std::bind(fun, std::placeholders::_1, batch_size));
65  }
66  public:
67  template<typename Rng, CONCEPT_REQUIRES_(ranges::ForwardRange<Rng>())>
68  forward_stream_t operator()(Rng&& rng, std::size_t batch_size = 1) const
69  {
71  ranges::view::chunk(std::forward<Rng>(rng), batch_size),
72  create_impl<Columns...>{});
73  }
74 
76  template<typename Rng, CONCEPT_REQUIRES_(!ranges::ForwardRange<Rng>())>
77  void operator()(Rng&&, std::size_t batch_size = 1) const
78  {
79  CONCEPT_ASSERT_MSG(ranges::ForwardRange<Rng>(),
80  "stream::create only works on ranges satisfying the ForwardRange concept.");
81  }
83  };
84 
85 } // namespace detail
86 
110 template<typename... Columns>
111 ranges::view::view<detail::create_fn<Columns...>> create{};
112 
113 } // end namespace hipipe::stream
ranges::any_view< batch_t, ranges::category::forward > forward_stream_t
The stream itself, i.e., a range of batches.
Definition: stream_t.hpp:24
constexpr auto tuple_for_each(Tuple &&tuple, Fun &&fun)
Apply a function on each element of a tuple.
Definition: tuple.hpp:119
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:187
Definition: ndim.hpp:144
ranges::view::view< detail::create_fn< Columns... > > create
Converts a data range to a HiPipe stream.
Definition: create.hpp:111
auto unzip(Rng range_of_tuples)
Unzips a range of tuples to a tuple of ranges.
Definition: tuple.hpp:257