passhash/include/nil/crypto3/detail/exploder.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 //
4 // MIT License
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
23 //---------------------------------------------------------------------------//
24 
25 #ifndef CRYPTO3_DETAIL_EXPLODER_HPP
26 #define CRYPTO3_DETAIL_EXPLODER_HPP
27 
28 #include <nil/crypto3/detail/stream_endian.hpp>
29 #include <nil/crypto3/detail/unbounded_shift.hpp>
30 
31 #include <boost/integer.hpp>
32 #include <boost/static_assert.hpp>
33 
34 #include <iterator>
35 
36 #include <climits>
37 #include <cstring>
38 
39 namespace nil {
40  namespace crypto3 {
41  namespace detail {
42 
43  // By definition, for all exploders, InputBits > OutputBits,
44  // so we're taking one value and splitting it into many smaller values
45 
46  template<typename OutIter, int OutBits, typename T = typename std::iterator_traits<OutIter>::value_type>
47  struct outvalue_helper {
48  typedef T type;
49  };
50  template<typename OutIter, int OutBits>
51  struct outvalue_helper<OutIter, OutBits, void> {
52  typedef typename boost::uint_t<OutBits>::least type;
53  };
54 
55  template<typename Endianness, int InputBits, int OutputBits, int k>
56  struct exploder_step;
57 
58  template<int UnitBits, int InputBits, int OutputBits, int k>
59  struct exploder_step<stream_endian::big_unit_big_bit<UnitBits>, InputBits, OutputBits, k> {
60  template<typename InputValue, typename OutIter>
61  static void step(InputValue const &x, OutIter &out) {
62  int const shift = InputBits - (OutputBits + k);
63  typedef typename outvalue_helper<OutIter, OutputBits>::type OutValue;
64  InputValue y = unbounded_shr<shift>(x);
65  *out++ = OutValue(low_bits<OutputBits>(y));
66  }
67  };
68 
69  template<int UnitBits, int InputBits, int OutputBits, int k>
70  struct exploder_step<stream_endian::little_unit_big_bit<UnitBits>, InputBits, OutputBits, k> {
71  template<typename InputValue, typename OutIter>
72  static void step(InputValue const &x, OutIter &out) {
73  int const kb = (k % UnitBits);
74  int const ku = k - kb;
75  int const shift =
76  OutputBits >= UnitBits ?
77  k :
78  InputBits >= UnitBits ? ku + (UnitBits - (OutputBits + kb)) : InputBits - (OutputBits + kb);
79  typedef typename outvalue_helper<OutIter, OutputBits>::type OutValue;
80  InputValue y = unbounded_shr<shift>(x);
81  *out++ = OutValue(low_bits<OutputBits>(y));
82  }
83  };
84 
85  template<int UnitBits, int InputBits, int OutputBits, int k>
86  struct exploder_step<stream_endian::big_unit_little_bit<UnitBits>, InputBits, OutputBits, k> {
87  template<typename InputValue, typename OutIter>
88  static void step(InputValue const &x, OutIter &out) {
89  int const kb = (k % UnitBits);
90  int const ku = k - kb;
91  int const shift = OutputBits >= UnitBits ?
92  InputBits - (OutputBits + k) :
93  InputBits >= UnitBits ? InputBits - (UnitBits + ku) + kb : kb;
94  typedef typename outvalue_helper<OutIter, OutputBits>::type OutValue;
95  InputValue y = unbounded_shr<shift>(x);
96  *out++ = OutValue(low_bits<OutputBits>(y));
97  }
98  };
99 
100  template<int UnitBits, int InputBits, int OutputBits, int k>
101  struct exploder_step<stream_endian::little_unit_little_bit<UnitBits>, InputBits, OutputBits, k> {
102  template<typename InputValue, typename OutIter>
103  static void step(InputValue const &x, OutIter &out) {
104  int const shift = k;
105  typedef typename outvalue_helper<OutIter, OutputBits>::type OutValue;
106  InputValue y = unbounded_shr<shift>(x);
107  *out++ = OutValue(low_bits<OutputBits>(y));
108  }
109  };
110 
111  template<int UnitBits, int InputBits, int OutputBits, int k>
112  struct exploder_step<stream_endian::host_unit<UnitBits>, InputBits, OutputBits, k> {
113  template<typename InputValue, typename OutIter>
114  static void step(InputValue const &x, OutIter &out) {
115  typedef typename outvalue_helper<OutIter, OutputBits>::type OutValue;
116  BOOST_STATIC_ASSERT(sizeof(InputValue) * CHAR_BIT == InputBits);
117  BOOST_STATIC_ASSERT(sizeof(OutValue) * CHAR_BIT == OutputBits);
118  OutValue value;
119  std::memcpy(&value, (char *)&x + k / CHAR_BIT, OutputBits / CHAR_BIT);
120  *out++ = value;
121  }
122  };
123 
124  template<typename Endianness, int InputBits, int OutputBits, int k = 0>
125  struct exploder;
126 
127  template<template<int> class Endian, int UnitBits, int InputBits, int OutputBits, int k>
128  struct exploder<Endian<UnitBits>, InputBits, OutputBits, k> {
129 
130  // To keep the implementation managable, input and output sizes must
131  // be multiples or factors of the unit size.
132  // If one of these is firing, you may want a bit-only stream_endian
133  // rather than one that mentions bytes or octets.
134  BOOST_STATIC_ASSERT(!(InputBits % UnitBits && UnitBits % InputBits));
135  BOOST_STATIC_ASSERT(!(OutputBits % UnitBits && UnitBits % OutputBits));
136 
137  typedef Endian<UnitBits> Endianness;
140 
141  template<typename InputValue, typename OutIter>
142  static void explode(InputValue const &x, OutIter &out) {
143  step_type::step(x, out);
144  next_type::explode(x, out);
145  }
146  };
147 
148  template<template<int> class Endian, int UnitBits, int InputBits, int OutputBits>
149  struct exploder<Endian<UnitBits>, InputBits, OutputBits, InputBits> {
150  template<typename InputValue, typename OutIter>
151  static void explode(InputValue const &, OutIter &) {
152  }
153  };
154 
155  } // namespace detail
156  } // namespace crypto3
157 } // namespace nil
158 
159 #endif // CRYPTO3_CODEC_DETAIL_EXPLODER_HPP
Definition: pair.hpp:31
exploder< Endianness, InputBits, OutputBits, k+OutputBits > next_type
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:139
BOOST_STATIC_ASSERT(!(InputBits % UnitBits &&UnitBits % InputBits))
exploder_step< Endianness, InputBits, OutputBits, k > step_type
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:138
Endian< UnitBits > Endianness
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:137
static void explode(InputValue const &x, OutIter &out)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:142
BOOST_STATIC_ASSERT(!(OutputBits % UnitBits &&UnitBits % OutputBits))
static void explode(InputValue const &, OutIter &)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:151
static void step(InputValue const &x, OutIter &out)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:61
static void step(InputValue const &x, OutIter &out)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:88
static void step(InputValue const &x, OutIter &out)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:114
static void step(InputValue const &x, OutIter &out)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:72
static void step(InputValue const &x, OutIter &out)
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:103
exploder_step obtains an output value represented in OutputEndianness endianness from an input value ...
Definition: block/include/nil/crypto3/detail/exploder.hpp:118
constexpr static int const shift
Definition: block/include/nil/crypto3/detail/exploder.hpp:119
exploder forms a sequence of output values represented in OutputEndianness endianness from an input v...
Definition: block/include/nil/crypto3/detail/exploder.hpp:148
boost::uint_t< OutBits >::least type
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:52
outvalue_helper trait is used to determine the output value type. If OutBits is not an exact power of...
Definition: block/include/nil/crypto3/detail/exploder.hpp:63
T type
Definition: passhash/include/nil/crypto3/detail/exploder.hpp:48