7 #include <multibase/algorithm.h>
8 #include <multibase/encoding.h>
20 static const std::array<char, 0> charset;
21 static const char name[];
22 static const char padding = 0;
28 template <encoding T,
typename Traits = traits<T>>
35 std::string
process(std::string_view input)
override;
38 constexpr
size_t input_size() {
return ratio.den; }
45 std::string
process(std::string_view input)
override;
48 constexpr
size_t input_size() {
return ratio.num; }
52 constexpr
static auto first = Traits::charset.cbegin();
53 constexpr
static auto last = Traits::charset.cend();
54 using CharsetT = decltype(Traits::charset);
55 using value_type =
typename CharsetT::value_type;
56 using iterator =
typename CharsetT::const_iterator;
59 constexpr
static iterator find(iterator b, iterator e,
60 value_type
const& v) noexcept {
61 return (b != e && *b != v) ? find(++b, e, v) : b;
66 constexpr
static unsigned char getval(
unsigned char p) noexcept {
67 return find(first, last, p) == last
68 ?
static_cast<unsigned char>(255)
69 :
static_cast<unsigned char>(
70 std::distance(first, find(first, last, p)));
74 constexpr
static std::intmax_t log2(std::intmax_t n) noexcept {
75 return (n == 1) ? 0 : ((n < 2) ? 1 : 1 + log2(n / 2));
79 constexpr
static auto radix =
sizeof(Traits::charset) /
sizeof(value_type);
81 constexpr
static auto ratio = std::ratio<log2(256), log2(radix)>{};
83 static const std::array<unsigned char, 256> valset;
85 constexpr
static auto base = T;
88 template <encoding T,
typename Traits>
89 const std::array<unsigned char, 256> basic_algorithm<T, Traits>::valset = {
90 getval(0), getval(1), getval(2), getval(3), getval(4),
91 getval(5), getval(6), getval(7), getval(8), getval(9),
92 getval(10), getval(11), getval(12), getval(13), getval(14),
93 getval(15), getval(16), getval(17), getval(18), getval(19),
94 getval(20), getval(21), getval(22), getval(23), getval(24),
95 getval(25), getval(26), getval(27), getval(28), getval(29),
96 getval(30), getval(31), getval(32), getval(33), getval(34),
97 getval(35), getval(36), getval(37), getval(38), getval(39),
98 getval(40), getval(41), getval(42), getval(43), getval(44),
99 getval(45), getval(46), getval(47), getval(48), getval(49),
100 getval(50), getval(51), getval(52), getval(53), getval(54),
101 getval(55), getval(56), getval(57), getval(58), getval(59),
102 getval(60), getval(61), getval(62), getval(63), getval(64),
103 getval(65), getval(66), getval(67), getval(68), getval(69),
104 getval(70), getval(71), getval(72), getval(73), getval(74),
105 getval(75), getval(76), getval(77), getval(78), getval(79),
106 getval(80), getval(81), getval(82), getval(83), getval(84),
107 getval(85), getval(86), getval(87), getval(88), getval(89),
108 getval(90), getval(91), getval(92), getval(93), getval(94),
109 getval(95), getval(96), getval(97), getval(98), getval(99),
110 getval(100), getval(101), getval(102), getval(103), getval(104),
111 getval(105), getval(106), getval(107), getval(108), getval(109),
112 getval(110), getval(111), getval(112), getval(113), getval(114),
113 getval(115), getval(116), getval(117), getval(118), getval(119),
114 getval(120), getval(121), getval(122), getval(123), getval(124),
115 getval(125), getval(126), getval(127), getval(128), getval(129),
116 getval(130), getval(131), getval(132), getval(133), getval(134),
117 getval(135), getval(136), getval(137), getval(138), getval(139),
118 getval(140), getval(141), getval(142), getval(143), getval(144),
119 getval(145), getval(146), getval(147), getval(148), getval(149),
120 getval(150), getval(151), getval(152), getval(153), getval(154),
121 getval(155), getval(156), getval(157), getval(158), getval(159),
122 getval(160), getval(161), getval(162), getval(163), getval(164),
123 getval(165), getval(166), getval(167), getval(168), getval(169),
124 getval(170), getval(171), getval(172), getval(173), getval(174),
125 getval(175), getval(176), getval(177), getval(178), getval(179),
126 getval(180), getval(181), getval(182), getval(183), getval(184),
127 getval(185), getval(186), getval(187), getval(188), getval(189),
128 getval(190), getval(191), getval(192), getval(193), getval(194),
129 getval(195), getval(196), getval(197), getval(198), getval(199),
130 getval(200), getval(201), getval(202), getval(203), getval(204),
131 getval(205), getval(206), getval(207), getval(208), getval(209),
132 getval(210), getval(211), getval(212), getval(213), getval(214),
133 getval(215), getval(216), getval(217), getval(218), getval(219),
134 getval(220), getval(221), getval(222), getval(223), getval(224),
135 getval(225), getval(226), getval(227), getval(228), getval(229),
136 getval(230), getval(231), getval(232), getval(233), getval(234),
137 getval(235), getval(236), getval(237), getval(238), getval(239),
138 getval(240), getval(241), getval(242), getval(243), getval(244),
139 getval(245), getval(246), getval(247), getval(248), getval(249),
140 getval(250), getval(251), getval(252), getval(253), getval(254),
143 template <encoding T,
typename Traits>
145 std::string_view input) {
147 std::size_t isize = input.size();
148 auto partial_blocks =
static_cast<float>(input.size()) / input_size();
149 auto num_blocks =
static_cast<std::size_t
>(partial_blocks);
150 auto osize =
static_cast<size_t>(std::ceil(partial_blocks *
output_size()));
151 if constexpr (std::is_same_v<typename Traits::execution_style, block_tag>) {
152 num_blocks =
static_cast<size_t>(std::ceil(partial_blocks));
153 isize = input_size() * num_blocks;
155 output.resize(std::max(osize, (
output_size() * num_blocks)));
156 auto input_it = std::begin(input);
158 for (std::size_t i = 0; i < isize; ++i, ++input_it) {
159 int carry = i >= input.size() ? 0 :
static_cast<unsigned char>(*input_it);
161 for (
auto oi = output.rbegin();
162 (oi != output.rend()) && (carry != 0 || j < length); ++oi, ++j) {
163 carry += 256 * (*oi);
164 auto byte = (
unsigned char*)(&(*oi));
165 *
byte = carry % radix;
170 std::transform(output.rbegin(), output.rend(), output.rbegin(),
171 [](
auto c) { return Traits::charset[c]; });
172 if constexpr (Traits::padding == 0) {
173 output.resize(osize);
175 auto pad_size = output.size() - osize;
176 output.replace(osize, pad_size, pad_size, Traits::padding);
178 if constexpr (std::is_same_v<typename Traits::execution_style, stream_tag>) {
179 output.erase(0, output.size() %
output_size() ? output.size() - length : 0);
184 template <encoding T,
typename Traits>
186 return std::is_same_v<typename Traits::execution_style, block_tag>
191 template <encoding T,
typename Traits>
196 template <encoding T,
typename Traits>
198 return std::is_same_v<typename Traits::execution_style, block_tag>
203 template <encoding T,
typename Traits>
208 template <encoding T,
typename Traits>
210 std::string_view input) {
212 auto end = std::find(input.begin(), input.end(), Traits::padding);
213 size_t input_size = std::distance(input.begin(), end);
214 auto partial_blocks =
static_cast<float>(input_size) / this->input_size();
215 auto output_size =
static_cast<size_t>(this->output_size() * partial_blocks);
216 if constexpr (std::is_same_v<typename Traits::execution_style, block_tag>) {
217 std::size_t num_blocks = 0;
218 auto input_size_float =
static_cast<float>(input.size());
220 static_cast<size_t>(std::ceil(input_size_float / this->input_size()));
221 output.resize(this->output_size() * num_blocks);
222 input_size = this->input_size() * num_blocks;
224 output.resize(output_size);
226 auto input_it = input.begin();
227 for (
size_t i = 0; i < input_size; ++i, ++input_it) {
228 int carry = i > input.size() || *input_it == Traits::padding
230 : valset[(
unsigned char)(*input_it)];
236 auto j = output.size();
237 while (carry != 0 || j > 0) {
239 carry += radix *
static_cast<unsigned char>(output[index]);
240 output[index] =
static_cast<unsigned char>(carry % 256);
242 if (carry > 0 && index == 0) {
243 output.insert(0, 1, 0);
249 if constexpr (std::is_same_v<typename Traits::execution_style, block_tag>) {
250 output.erase(output_size, output.size());
257 constexpr
static const std::array<char, 16> charset = {
258 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
259 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'};
260 constexpr
static const char name[] =
"base_16";
262 constexpr
static const char padding = 0;
268 constexpr
static const std::array<char, 36> charset = {
269 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
270 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
271 'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
272 'u',
'v',
'w',
'x',
'y',
'z'};
273 constexpr
static const char name[] =
"base_36";
275 constexpr
static const char padding = 0;
282 constexpr
static const std::array<char, 58> charset = {
283 '1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F',
284 'G',
'H',
'J',
'K',
'L',
'M',
'N',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
285 'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'm',
286 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z'};
287 constexpr
static const char name[] =
"base_58_btc";
289 constexpr
static const char padding = 0;
295 constexpr
static const std::array<char, 64> charset = {
296 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
297 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
298 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
299 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
300 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
301 constexpr
static const char name[] =
"base_64_pad";
303 constexpr
static const char padding =
'=';
309 constexpr
static const std::array<char, 64> charset = {
310 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
311 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
312 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
313 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
314 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
315 constexpr
static const char name[] =
"base_64";
318 constexpr
static const char padding = 0;
Definition: algorithm.h:11
Definition: algorithm.h:14
Definition: algorithm.h:8
Definition: basic_algorithm.h:41
size_t block_size() override
Definition: basic_algorithm.h:197
std::string process(std::string_view input) override
Definition: basic_algorithm.h:209
size_t output_size() override
Definition: basic_algorithm.h:204
Definition: basic_algorithm.h:31
size_t output_size() override
Definition: basic_algorithm.h:192
size_t block_size() override
Definition: basic_algorithm.h:185
std::string process(std::string_view input) override
Definition: basic_algorithm.h:144
Definition: basic_algorithm.h:29
Definition: basic_algorithm.h:19