|
#ifndef LM_INTERPOLATE_BOUNDED_SEQUENCE_ENCODING_H |
|
#define LM_INTERPOLATE_BOUNDED_SEQUENCE_ENCODING_H |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "../../util/exception.hh" |
|
#include "../../util/fixed_array.hh" |
|
|
|
#include <algorithm> |
|
#include <cstring> |
|
|
|
namespace lm { |
|
namespace interpolate { |
|
|
|
class BoundedSequenceEncoding { |
|
public: |
|
|
|
BoundedSequenceEncoding(const unsigned char *bound_begin, const unsigned char *bound_end); |
|
|
|
std::size_t Entries() const { return entries_.size(); } |
|
|
|
std::size_t EncodedLength() const { return byte_length_; } |
|
|
|
void Encode(const unsigned char *from, void *to_void) const { |
|
uint8_t *to = static_cast<uint8_t*>(to_void); |
|
uint64_t cur = 0; |
|
for (const Entry *i = entries_.begin(); i != entries_.end(); ++i, ++from) { |
|
if (UTIL_UNLIKELY(i->next)) { |
|
std::memcpy(to, &cur, sizeof(uint64_t)); |
|
to += sizeof(uint64_t); |
|
cur = 0; |
|
} |
|
cur |= static_cast<uint64_t>(*from) << i->shift; |
|
} |
|
#if BYTE_ORDER == BIG_ENDIAN |
|
cur <<= (8 - overhang_) * 8; |
|
#endif |
|
memcpy(to, &cur, overhang_); |
|
} |
|
|
|
void Decode(const void *from_void, unsigned char *to) const { |
|
const uint8_t *from = static_cast<const uint8_t*>(from_void); |
|
uint64_t cur = 0; |
|
memcpy(&cur, from, first_copy_); |
|
#if BYTE_ORDER == BIG_ENDIAN |
|
cur >>= (8 - first_copy_) * 8; |
|
#endif |
|
for (const Entry *i = entries_.begin(); i != entries_.end(); ++i, ++to) { |
|
if (UTIL_UNLIKELY(i->next)) { |
|
from += sizeof(uint64_t); |
|
cur = 0; |
|
std::memcpy(&cur, from, |
|
std::min<std::size_t>(sizeof(uint64_t), static_cast<const uint8_t*>(from_void) + byte_length_ - from)); |
|
#if BYTE_ORDER == BIG_ENDIAN |
|
cur >>= (8 - (static_cast<const uint8_t*>(from_void) + byte_length_ - from)) * 8; |
|
#endif |
|
} |
|
*to = (cur >> i->shift) & i->mask; |
|
} |
|
} |
|
|
|
private: |
|
struct Entry { |
|
bool next; |
|
uint8_t shift; |
|
uint64_t mask; |
|
}; |
|
util::FixedArray<Entry> entries_; |
|
std::size_t byte_length_; |
|
std::size_t first_copy_; |
|
std::size_t overhang_; |
|
}; |
|
|
|
|
|
}} |
|
|
|
#endif |
|
|