48 const char alphabet[] =
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
49 const size_t alphabet_size =
sizeof(alphabet) - 1;
50 const size_t encoded_block_sizes[] = {0, 2, 3, 5, 6, 7, 9, 10, 11};
51 const size_t full_block_size =
sizeof(encoded_block_sizes) /
sizeof(encoded_block_sizes[0]) - 1;
52 const size_t full_encoded_block_size = encoded_block_sizes[full_block_size];
53 const size_t addr_checksum_size = 4;
55 struct reverse_alphabet
59 m_data.resize(alphabet[alphabet_size - 1] - alphabet[0] + 1, -1);
61 for (
size_t i = 0; i < alphabet_size; ++i)
63 size_t idx =
static_cast<size_t>(alphabet[i] - alphabet[0]);
64 m_data[idx] =
static_cast<int8_t>(i);
68 int operator()(
char letter)
const 70 size_t idx =
static_cast<size_t>(letter - alphabet[0]);
71 return idx < m_data.size() ? m_data[idx] : -1;
74 static reverse_alphabet instance;
77 std::vector<int8_t> m_data;
80 reverse_alphabet reverse_alphabet::instance;
82 struct decoded_block_sizes
86 m_data.resize(encoded_block_sizes[full_block_size] + 1, -1);
87 for (
size_t i = 0; i <= full_block_size; ++i)
89 m_data[encoded_block_sizes[i]] =
static_cast<int>(i);
93 int operator()(
size_t encoded_block_size)
const 95 assert(encoded_block_size <= full_encoded_block_size);
96 return m_data[encoded_block_size];
99 static decoded_block_sizes instance;
102 std::vector<int> m_data;
105 decoded_block_sizes decoded_block_sizes::instance;
109 assert(1 <= size && size <=
sizeof(
uint64_t));
118 assert(1 <= size && size <=
sizeof(
uint64_t));
121 memcpy(data, reinterpret_cast<uint8_t*>(&num_be) +
sizeof(
uint64_t) - size, size);
124 void encode_block(
const char* block,
size_t size,
char*
res)
126 assert(1 <= size && size <= full_block_size);
128 uint64_t num = uint_8be_to_64(reinterpret_cast<const uint8_t*>(block), size);
129 int i =
static_cast<int>(encoded_block_sizes[size]) - 1;
132 uint64_t remainder = num % alphabet_size;
133 num /= alphabet_size;
134 res[i] = alphabet[remainder];
139 bool decode_block(
const char* block,
size_t size,
char*
res)
141 assert(1 <= size && size <= full_encoded_block_size);
143 int res_size = decoded_block_sizes::instance(size);
149 for (
size_t i = size - 1; i < size; --i)
151 int digit = reverse_alphabet::instance(block[i]);
156 uint64_t tmp = res_num + mul128(order, digit, &product_hi);
157 if (tmp < res_num || 0 != product_hi)
161 order *= alphabet_size;
164 if (static_cast<size_t>(res_size) < full_block_size && (
UINT64_C(1) << (8 * res_size)) <= res_num)
167 uint_64_to_8be(res_num, res_size, reinterpret_cast<uint8_t*>(
res));
178 size_t full_block_count = data.size() / full_block_size;
179 size_t last_block_size = data.size() % full_block_size;
180 size_t res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size];
183 for (
size_t i = 0; i < full_block_count; ++i)
185 encode_block(data.data() + i * full_block_size, full_block_size, &
res[i * full_encoded_block_size]);
188 if (0 < last_block_size)
190 encode_block(data.data() + full_block_count * full_block_size, last_block_size, &
res[full_block_count * full_encoded_block_size]);
204 size_t full_block_count = enc.size() / full_encoded_block_size;
205 size_t last_block_size = enc.size() % full_encoded_block_size;
206 int last_block_decoded_size = decoded_block_sizes::instance(last_block_size);
207 if (last_block_decoded_size < 0)
209 size_t data_size = full_block_count * full_block_size + last_block_decoded_size;
211 data.resize(data_size, 0);
212 for (
size_t i = 0; i < full_block_count; ++i)
214 if (!decode_block(enc.data() + i * full_encoded_block_size, full_encoded_block_size, &data[i * full_block_size]))
218 if (0 < last_block_size)
220 if (!decode_block(enc.data() + full_block_count * full_encoded_block_size, last_block_size,
221 &data[full_block_count * full_block_size]))
233 const char* hash_data =
reinterpret_cast<const char*
>(&
hash);
234 buf.append(hash_data, addr_checksum_size);
241 bool r =
decode(addr, addr_data);
242 if (!r)
return false;
243 if (addr_data.size() <= addr_checksum_size)
return false;
246 checksum = addr_data.substr(addr_data.size() - addr_checksum_size);
248 addr_data.resize(addr_data.size() - addr_checksum_size);
250 std::string expected_checksum(reinterpret_cast<const char*>(&
hash), addr_checksum_size);
251 if (expected_checksum != checksum)
return false;
253 int read = tools::read_varint(addr_data.begin(), addr_data.end(), tag);
254 if (read <= 0)
return false;
256 data = addr_data.substr(read);
provides the implementation of varint's
unsigned __int64 uint64_t
void cn_fast_hash(const void *data, size_t length, char *hash)
void * memcpy(void *a, const void *b, size_t c)