<tb@panthema.net>
<http://www.gnu.org/licenses/>
namespace stringtools {
typedef unsigned char* string;
typedef unsigned int uint128_t __attribute__((mode(TI)));
template <typename Type>
static inline std::string toHex(Type v)
{
char out[2 * sizeof(v)+1];
static const char hex[17] = "0123456789ABCDEF";
for (unsigned int i = 1; i <= sizeof(v); ++i)
{
out[2*(sizeof(v)-i)+0] = hex[(v & 0xF0) >> 4];
out[2*(sizeof(v)-i)+1] = hex[(v & 0x0F) >> 0];
v >>= 8;
}
out[2*sizeof(v)] = 0;
return out;
}
template <typename Type>
static inline std::string toBinary(Type v)
{
static const int w = (1 << sizeof(v));
char binstr[w+1];
binstr[w] = 0;
for (int i = 0; i < w; i++) {
binstr[w-i-1] = (v & 1) ? '1' : '0';
v /= 2;
}
return binstr;
}
template <typename CharT>
class key_traits {
};
template <>
class key_traits<uint8_t> {
public:
static const size_t radix = 256;
static const size_t add_depth = 1;
};
template <>
class key_traits<uint16_t> {
public:
static const size_t radix = 65536;
static const size_t add_depth = 2;
};
template <typename CharT>
inline CharT get_char(string ptr, size_t depth);
template <>
inline uint8_t get_char<uint8_t>(string str, size_t depth)
{
return (uint8_t)(str[depth]);
}
template <>
inline uint16_t get_char<uint16_t>(string str, size_t depth)
{
uint16_t v = 0;
if (str[depth] == 0) return v;
v |= (uint16_t(str[depth]) << 8); ++str;
v |= (uint16_t(str[depth]) << 0);
return v;
}
template <>
inline uint32_t get_char<uint32_t>(string str, size_t depth)
{
uint32_t v = 0;
if (str[depth] == 0) return v;
v |= (uint32_t(str[depth]) << 24); ++str;
if (str[depth] == 0) return v;
v |= (uint32_t(str[depth]) << 16); ++str;
if (str[depth] == 0) return v;
v |= (uint32_t(str[depth]) << 8); ++str;
v |= (uint32_t(str[depth]) << 0);
return v;
}
template <>
inline uint64_t get_char<uint64_t>(string str, size_t depth)
{
#if 0
uint64_t v = 0;
if (str[depth] == 0) return v;
v = (uint64_t(str[depth]) << 56); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 48); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 40); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 32); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 24); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 16); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 8); ++str;
v |= (uint64_t(str[depth]) << 0);
return v;
#else
uint64_t v = __builtin_bswap64( *(uint64_t*)(str+depth) );
if ( (v & 0xFF00000000000000LLU) == 0 )
return 0;
else if ( (v & 0x00FF000000000000LLU) == 0 )
return (v & 0xFFFF000000000000LLU);
else if ( (v & 0x0000FF0000000000LLU) == 0 )
return (v & 0xFFFFFF0000000000LLU);
else if ( (v & 0x000000FF00000000LLU) == 0 )
return (v & 0xFFFFFFFF00000000LLU);
else if ( (v & 0x00000000FF000000LLU) == 0 )
return (v & 0xFFFFFFFFFF000000LLU);
else if ( (v & 0x0000000000FF0000LLU) == 0 )
return (v & 0xFFFFFFFFFFFF0000LLU);
else if ( (v & 0x000000000000FF00LLU) == 0 )
return (v & 0xFFFFFFFFFFFFFF00LLU);
return v;
#endif
}
template <>
inline uint128_t get_char<uint128_t>(string str, size_t depth)
{
uint128_t v = 0;
if (str[depth] == 0) return v;
v = (uint128_t(str[depth]) << 120); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 112); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 104); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 96); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 88); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 80); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 72); ++str;
if (str[depth] == 0) return v;
v |= (uint128_t(str[depth]) << 64); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 56); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 48); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 40); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 32); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 24); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 16); ++str;
if (str[depth] == 0) return v;
v |= (uint64_t(str[depth]) << 8); ++str;
v |= (uint64_t(str[depth]) << 0);
return v;
}
template <typename T>
inline int count_high_zero_bits(const T& t);
template <>
inline int count_high_zero_bits<uint32_t>(const uint32_t& t)
{
if (t == 0) return sizeof(t) * 8;
return __builtin_clz(t);
}
template <>
inline int count_high_zero_bits<uint64_t>(const uint64_t& t)
{
if (t == 0) return sizeof(t) * 8;
return __builtin_clzll(t);
}
template <>
inline int count_high_zero_bits<uint128_t>(const uint128_t& t)
{
if (t == 0) return sizeof(t) * 8;
uint64_t hi = (t >> 64);
int b = __builtin_clzll(hi);
if (b > 0)
return b;
else
return 64 + __builtin_clzll( (uint64_t)t );
}
class StringPtr
{
public:
string *m_front, *m_back;
bool m_flip;
inline StringPtr(string* front, string* back = NULL, bool flip = false)
: m_front(front), m_back(back), m_flip(flip)
{
}
inline bool flipped() const
{
return m_flip;
}
inline string* active()
{
return (m_flip ? m_back : m_front);
}
inline string* shadow()
{
return (m_flip ? m_front : m_back);
}
inline StringPtr flip_ptr(size_t offset) const
{
return StringPtr(m_front + offset, m_back + offset, !m_flip);
}
inline string* to_original(size_t n)
{
if (m_flip) {
assert(m_back);
memcpy(m_front, m_back, n * sizeof(string));
m_flip = false;
}
return m_front;
}
};
}