You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pEpJSONServerAdapter/server/registry.cc

135 lines
3.0 KiB
C++

#include "registry.hh"
#include <algorithm>
#include <iostream>
// mix the bits of 'value' into a less-
uint64_t joggle(uint64_t realm, uint64_t value)
{
++value;
value ^= realm;
value *= 11400714819323198485ull; // golden ratio (0.618...) * 2^64
value = (value>>19) | (value<<(64-19)); // bit rotate right by 19 bits
return realm - value;
}
uint64_t unjoggle(uint64_t realm, uint64_t value)
{
value = realm - value;
value = (value<<19) | (value>>(64-19)); // bit rotate left by 19 bits
value *= 17428512612931826493ull; // inv_mod( 11400714819323198485, 2^64 );
return (value ^ realm)-1;
}
namespace
{
const char* const alphabet = "98765432aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ";
int8_t reverse[256];
struct Alphabet
{
Alphabet()
{
std::fill(reverse, reverse+256, -1 );
uint8_t u = 0;
const char* a = alphabet;
while(*a)
{
reverse[uint8_t(*a)] = u;
++a;
++u;
}
std::cout << "initialize " << int(u) << " elements of the reverse map.\n";
}
};
// Alphabet static_initialize_reverse_array;
}
std::string base57(std::uint64_t x)
{
char buffer[12] = "+.:-*^?-#~$";
for(unsigned u=0; u<11; ++u)
{
buffer[u] = alphabet[ x % 57 ];
x/=57;
}
return std::string(buffer, buffer+11);
}
std::uint64_t unbase57(const std::string& s)
{
static Alphabet nono;
if(s.size() != 11)
throw std::runtime_error("Invalid base57 string! Length=" + std::to_string(s.size()) + ". \"" + s + "\" is not a valid base62-encoded 64 bit integer");
std::uint64_t ret = 0;
std::uint64_t factor = 1;
for(unsigned u=0; u<11; ++u)
{
int f = reverse[ uint8_t(s[u]) ];
if(f<0)
throw std::runtime_error("At position " + std::to_string(u) + ": Invalid char '" + std::to_string( int(s[u]) ) + "'");
ret += f*factor;
factor *= 57;
}
return ret;
}
unsigned test_joggle()
{
for(unsigned u=0; u<99; ++u)
{
const uint64_t j = joggle( 0xCAFEBABE00000000, u );
const std::string s = base57(j);
std::cout << "# u=" << u << ", j=" << j << ", s=\"" << s << "\".\n";
const uint64_t jj = joggle( 00, u );
const std::string ss = base57(jj);
std::cout << "# j=" << jj << ", s=\"" << ss << "\".\n";
}
uint64_t counter = 0;
for(uint64_t realm = 100; realm < 0xAAAA000011117777; realm = uint64_t(realm*1.123))
for(uint64_t u = 0; u < 0x9999ffff00009999; u = uint64_t(u*1.171+1))
{
++counter;
const uint64_t j = joggle( realm, u );
const uint64_t jj = unjoggle( realm, j );
if( jj!=u )
{
std::cerr << "Joggle mismatch! realm=" << realm << ", u = " << u << ", j = " << j << ", jj = " << jj << ".\n";
return 1;
}
const std::string s = base57(j);
const uint64_t us = unbase57(s);
if( us != j )
{
std::cerr << "base57 mismatch! j = " << j << ", s = " << s << ", us = " << us << ".\n";
return 2;
}
if( ((u*1111^0x777) + (realm*777^0xaaaa))%77777==0)
{
std::cout << "#" << counter << ": realm=" << realm << ", u=" << u << ", j=" << j << ", s=\"" << s << "\".\n";
}
}
std::cout << counter << " values checked successfully. :-)\n";
return 0;
}