47 const char alphabet[] =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
48 const size_t alphabet_size =
sizeof(alphabet) - 1;
49 const size_t encoded_block_sizes[] = {0, 2, 3, 5, 6, 7, 9, 10, 11};
50 const size_t full_block_size =
sizeof(encoded_block_sizes) /
sizeof(encoded_block_sizes[0]) - 1;
51 const size_t full_encoded_block_size = encoded_block_sizes[full_block_size];
52 const size_t addr_checksum_size = 4;
54 struct reverse_alphabet
58 m_data.resize(alphabet[alphabet_size - 1] - alphabet[0] + 1, -1);
60 for (
size_t i = 0; i < alphabet_size; ++i)
62 size_t idx =
static_cast<size_t>(alphabet[i] - alphabet[0]);
63 m_data[idx] =
static_cast<int8_t>(i);
67 int operator()(
char letter)
const
69 size_t idx =
static_cast<size_t>(letter - alphabet[0]);
70 return idx < m_data.size() ? m_data[idx] : -1;
73 static reverse_alphabet instance;
76 std::vector<int8_t> m_data;
79 reverse_alphabet reverse_alphabet::instance;
81 struct decoded_block_sizes
85 m_data.resize(encoded_block_sizes[full_block_size] + 1, -1);
86 for (
size_t i = 0; i <= full_block_size; ++i)
88 m_data[encoded_block_sizes[i]] =
static_cast<int>(i);
92 int operator()(
size_t encoded_block_size)
const
94 assert(encoded_block_size <= full_encoded_block_size);
95 return m_data[encoded_block_size];
98 static decoded_block_sizes instance;
101 std::vector<int> m_data;
104 decoded_block_sizes decoded_block_sizes::instance;
108 assert(1 <= size && size <=
sizeof(
uint64_t));
117 assert(1 <= size && size <=
sizeof(
uint64_t));
123 void encode_block(
const char*
block,
size_t size,
char*
res)
125 assert(1 <= size && size <= full_block_size);
128 int i =
static_cast<int>(encoded_block_sizes[size]) - 1;
131 uint64_t remainder = num % alphabet_size;
132 num /= alphabet_size;
133 res[i] = alphabet[remainder];
138 bool decode_block(
const char*
block,
size_t size,
char*
res)
140 assert(1 <= size && size <= full_encoded_block_size);
142 int res_size = decoded_block_sizes::instance(size);
148 for (
size_t i = size - 1; i < size; --i)
150 int digit = reverse_alphabet::instance(
block[i]);
156 if (tmp < res_num || 0 != product_hi)
160 order *= alphabet_size;
163 if (
static_cast<size_t>(res_size) < full_block_size && (
UINT64_C(1) << (8 * res_size)) <= res_num)
166 uint_64_to_8be(res_num, res_size,
reinterpret_cast<uint8_t*
>(
res));
175 return std::string();
177 size_t full_block_count =
data.size() / full_block_size;
178 size_t last_block_size =
data.size() % full_block_size;
179 size_t res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size];
181 std::string
res(res_size, alphabet[0]);
182 for (
size_t i = 0; i < full_block_count; ++i)
184 encode_block(
data.data() + i * full_block_size, full_block_size, &
res[i * full_encoded_block_size]);
187 if (0 < last_block_size)
189 encode_block(
data.data() + full_block_count * full_block_size, last_block_size, &
res[full_block_count * full_encoded_block_size]);
203 size_t full_block_count = enc.size() / full_encoded_block_size;
204 size_t last_block_size = enc.size() % full_encoded_block_size;
205 int last_block_decoded_size = decoded_block_sizes::instance(last_block_size);
206 if (last_block_decoded_size < 0)
208 size_t data_size = full_block_count * full_block_size + last_block_decoded_size;
210 data.resize(data_size, 0);
211 for (
size_t i = 0; i < full_block_count; ++i)
213 if (!decode_block(enc.data() + i * full_encoded_block_size, full_encoded_block_size, &
data[i * full_block_size]))
217 if (0 < last_block_size)
219 if (!decode_block(enc.data() + full_block_count * full_encoded_block_size, last_block_size,
220 &
data[full_block_count * full_block_size]))
232 const char* hash_data =
reinterpret_cast<const char*
>(&hash);
233 buf.append(hash_data, addr_checksum_size);
239 std::string addr_data;
240 bool r =
decode(addr, addr_data);
241 if (!r)
return false;
242 if (addr_data.size() <= addr_checksum_size)
return false;
244 std::string checksum(addr_checksum_size,
'\0');
245 checksum = addr_data.substr(addr_data.size() - addr_checksum_size);
247 addr_data.resize(addr_data.size() - addr_checksum_size);
249 std::string expected_checksum(
reinterpret_cast<const char*
>(&hash), addr_checksum_size);
250 if (expected_checksum != checksum)
return false;
253 if (read <= 0)
return false;
255 data = addr_data.substr(read);
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16