25 #ifndef CRYPTO3_DETAIL_PACK_HPP
26 #define CRYPTO3_DETAIL_PACK_HPP
28 #include <nil/crypto3/detail/type_traits.hpp>
29 #include <nil/crypto3/detail/stream_endian.hpp>
30 #include <nil/crypto3/detail/exploder.hpp>
31 #include <nil/crypto3/detail/imploder.hpp>
32 #include <nil/crypto3/detail/predef.hpp>
34 #include <boost/assert.hpp>
35 #include <boost/static_assert.hpp>
37 #ifndef CRYPTO3_NO_OPTIMIZATION
39 #include <boost/endian.hpp>
40 #include <boost/utility/enable_if.hpp>
47 #ifndef CRYPTO3_NO_OPTIMIZATION
49 template<
int UnitBits,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
50 struct host_can_memcpy {
51 static bool const value = !(UnitBits % CHAR_BIT) && InputBits >= UnitBits && OutputBits >= UnitBits &&
52 sizeof(InT) * CHAR_BIT == InputBits &&
sizeof(OutT) * CHAR_BIT == OutputBits;
55 template<
typename Endianness,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
57 static bool const value = InputBits == OutputBits &&
sizeof(InT) ==
sizeof(OutT);
60 template<
int UnitBits,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
61 struct can_memcpy<stream_endian::host_unit<UnitBits>, InputBits, OutputBits, InT, OutT>
64 #ifdef BOOST_ENDIAN_LITTLE_BYTE_AVAILABLE
65 template<
int UnitBits,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
66 struct can_memcpy<stream_endian::little_unit_big_bit<UnitBits>, InputBits, OutputBits, InT, OutT>
67 : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
68 template<
int UnitBits,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
69 struct can_memcpy<stream_endian::little_unit_little_bit<UnitBits>, InputBits, OutputBits, InT, OutT>
70 : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
73 #ifdef CRYPTO3_TARGET_CPU_IS_BIG_ENDIAN
74 template<
int UnitBits,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
75 struct can_memcpy<stream_endian::big_unit_big_bit<UnitBits>, InputBits, OutputBits, InT, OutT>
76 : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
77 template<
int UnitBits,
int InputBits,
int OutputBits,
typename InT,
typename OutT>
78 struct can_memcpy<stream_endian::big_unit_little_bit<UnitBits>, InputBits, OutputBits, InT, OutT>
79 : host_can_memcpy<UnitBits, InputBits, OutputBits, InT, OutT> {};
84 template<
typename Endianness,
int InputBits,
int OutputBits,
bool Explode = (InputBits > OutputBits),
85 bool Implode = (InputBits < OutputBits)>
88 template<
typename Endianness,
int Bits>
89 struct real_packer<Endianness, Bits, Bits, false, false> {
91 template<
typename InIter,
typename OutIter>
92 static void pack_n(InIter in,
size_t in_n, OutIter out) {
93 std::copy(in, in + in_n, out);
96 template<
typename InIter,
typename OutIter>
97 static void pack(InIter in, InIter in_e, OutIter out) {
98 std::copy(in, in_e, out);
102 template<
typename Endianness,
int InputBits,
int OutputBits>
103 struct real_packer<Endianness, InputBits, OutputBits, true, false> {
107 template<
typename InIter,
typename OutIter>
108 static void pack_n(InIter in,
size_t in_n, OutIter out) {
110 typedef typename std::iterator_traits<InIter>::value_type InValue;
111 InValue
const value = *in++;
116 template<
typename InIter,
typename OutIter>
117 static void pack(InIter in, InIter in_e, OutIter out) {
119 typedef typename std::iterator_traits<InIter>::value_type InValue;
120 InValue
const value = *in++;
126 template<
typename Endianness,
int InputBits,
int OutputBits>
127 struct real_packer<Endianness, InputBits, OutputBits, false, true> {
131 template<
typename InIter,
typename OutIter>
132 static void pack_n(InIter in,
size_t in_n, OutIter out) {
133 size_t out_n = in_n / (OutputBits / InputBits);
136 OutValue value = OutValue();
142 template<
typename InIter,
typename OutIter>
143 static void pack(InIter in, InIter in_e, OutIter out) {
146 OutValue value = OutValue();
153 template<
typename Endianness,
int InputBits,
int OutputBits>
154 struct packer : real_packer<Endianness, InputBits, OutputBits> {
156 #ifndef CRYPTO3_NO_OPTIMIZATION
160 template<
typename InT,
typename OutT>
161 static typename std::enable_if<can_memcpy<Endianness, InputBits, OutputBits, InT, OutT>::value>::type
162 pack_n(InT
const *in,
size_t n, OutT *out) {
163 std::memcpy(out, in, n *
sizeof(InT));
166 template<
typename InT,
typename OutT>
167 static typename std::enable_if<can_memcpy<Endianness, InputBits, OutputBits, InT, OutT>::value>::type
169 std::memcpy(out, in, n *
sizeof(InT));
175 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
176 typename InputIterator2>
177 void pack_n(InputIterator1 in,
size_t in_n, InputIterator2 out) {
178 typedef packer<Endianness, InValueBits, OutValueBits> packer_type;
182 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
183 typename InputIterator2>
184 void pack_n(InputIterator1 in,
size_t in_n, InputIterator2 out,
size_t out_n) {
185 BOOST_ASSERT(in_n * InValueBits == out_n * OutValueBits);
186 pack_n<Endianness, InValueBits, OutValueBits>(in, in_n, out);
189 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
190 typename InputIterator2>
191 void pack(InputIterator1 b1, InputIterator1 e1, std::random_access_iterator_tag, InputIterator2 b2) {
192 pack_n<Endianness, InValueBits, OutValueBits>(b1, e1 - b1, b2);
195 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
typename CatT1,
196 typename InputIterator2,
197 typename =
typename std::enable_if<detail::is_iterator<InputIterator1>::value>::type,
198 typename =
typename std::enable_if<detail::is_iterator<InputIterator2>::value>::type>
199 void pack(InputIterator1 b1, InputIterator1 e1, CatT1, InputIterator2 b2) {
200 typedef packer<Endianness, InValueBits, OutValueBits> packer_type;
204 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
205 typename InputIterator2,
206 typename =
typename std::enable_if<detail::is_iterator<InputIterator2>::value>::type>
207 void pack(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2) {
208 typedef typename std::iterator_traits<InputIterator1>::iterator_category cat1;
209 pack<Endianness, InValueBits, OutValueBits>(b1, e1, cat1(), b2);
212 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
213 typename InputIterator2>
214 void pack(InputIterator1 b1, InputIterator1 e1, std::random_access_iterator_tag, InputIterator2 b2,
215 InputIterator2 e2, std::random_access_iterator_tag) {
216 pack_n<Endianness, InValueBits, OutValueBits>(b1, e1 - b1, b2, e2 - b2);
219 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
typename CatT1,
220 typename InputIterator2,
typename CatT2>
221 void pack(InputIterator1 b1, InputIterator1 e1, CatT1, InputIterator2 b2, InputIterator2, CatT2) {
222 pack<Endianness, InValueBits, OutValueBits>(b1, e1, b2);
225 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator1,
226 typename InputIterator2>
227 void pack(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2) {
228 typedef typename std::iterator_traits<InputIterator1>::iterator_category cat1;
229 typedef typename std::iterator_traits<InputIterator2>::iterator_category cat2;
230 pack<Endianness, InValueBits, OutValueBits>(b1, e1, cat1(), b2, e2, cat2());
233 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputType,
typename OutputType>
234 void pack(
const InputType &in, OutputType &out) {
235 pack_n<Endianness, InValueBits, OutValueBits>(in.data(), in.size(), out.data(), out.size());
238 template<
typename Endianness,
int InValueBits,
int OutValueBits,
typename InputIterator,
240 typename =
typename std::enable_if<!std::is_arithmetic<OutputType>::value>::type>
241 inline void pack(InputIterator first, InputIterator last, OutputType &out) {
242 pack_n<Endianness, InValueBits, OutValueBits>(first, std::distance(first, last), out.begin(),
void pack_n(InputIterator in, std::size_t in_n, OutputIterator out)
Packs in_n input elements starting from in into output elements beginning from out.
Definition: block/include/nil/crypto3/detail/pack.hpp:776
void pack(InputIterator first, InputIterator last, std::random_access_iterator_tag, OutputIterator out)
Packs elements from the range [first, last) into elements starting from out. Works for input containe...
Definition: block/include/nil/crypto3/detail/pack.hpp:835
can_memcpy trait is derived from host_can_memcpy trait and is invoked depending on data endianness....
Definition: block/include/nil/crypto3/detail/pack.hpp:90
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/pack.hpp:91
exploder forms a sequence of output values represented in OutputEndianness endianness from an input v...
Definition: block/include/nil/crypto3/detail/exploder.hpp:148
The group of traits below is used to determine the possibility of fast data copy. By fast data copy w...
Definition: block/include/nil/crypto3/detail/pack.hpp:71
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/pack.hpp:72
imploder processes a sequence of input values represented in InputEndianness endianness into an outpu...
Definition: block/include/nil/crypto3/detail/imploder.hpp:122
T type
Definition: block/include/nil/crypto3/detail/exploder.hpp:64
static std::enable_if< can_memcpy< Endianness, InputBits, OutputBits, InT, OutT >::value >::type pack_n(InT const *in, size_t n, OutT *out)
Definition: stream/include/nil/crypto3/detail/pack.hpp:162
static std::enable_if< can_memcpy< Endianness, InputBits, OutputBits, InT, OutT >::value >::type pack_n(InT *in, size_t n, OutT *out)
Definition: stream/include/nil/crypto3/detail/pack.hpp:168
static void pack_n(InIter in, size_t in_n, OutIter out)
Definition: stream/include/nil/crypto3/detail/pack.hpp:92
static void pack(InIter in, InIter in_e, OutIter out)
Definition: stream/include/nil/crypto3/detail/pack.hpp:97