67 lines
1.7 KiB
C++
67 lines
1.7 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "../view.hpp"
|
|
#include "../maths.hpp"
|
|
|
|
#include <array>
|
|
#include <limits>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
namespace cruft::encode {
|
|
template <typename ValueT>
|
|
ValueT
|
|
decode36 (cruft::view<char const*> &src)
|
|
{
|
|
ValueT accum = 0;
|
|
for (auto const i: src) {
|
|
accum *= 36;
|
|
|
|
switch (i) {
|
|
case '0'...'9': accum += i - '0'; continue;
|
|
case 'a'...'z': accum += i - 'a' + 10; continue;
|
|
case 'A'...'Z': accum += i - 'A' + 10; continue;
|
|
default:
|
|
throw std::invalid_argument ("invalid character");
|
|
}
|
|
}
|
|
|
|
return accum;
|
|
}
|
|
|
|
|
|
template <typename ValueT, typename OutputT>
|
|
OutputT
|
|
encode36 (OutputT out, ValueT val)
|
|
{
|
|
constexpr auto count = digits(std::numeric_limits<ValueT>::max (), 36u);
|
|
std::array<char, count> res;
|
|
|
|
auto cursor = res.begin ();
|
|
// Ensure we do at least one iteration so we output a zero.
|
|
do {
|
|
switch (auto const d = val % 36; d) {
|
|
case 0 ... 9: *cursor = d + '0'; break;
|
|
case 10 ...35: *cursor = d - 10 + 'a'; break;
|
|
}
|
|
|
|
val /= 36;
|
|
++cursor;
|
|
} while (val);
|
|
|
|
return std::copy (
|
|
std::make_reverse_iterator (cursor),
|
|
res.rend (),
|
|
out
|
|
);
|
|
}
|
|
}
|