mirror of
https://github.com/moses-smt/mosesdecoder.git
synced 2025-01-06 19:49:41 +03:00
127 lines
3.3 KiB
C++
127 lines
3.3 KiB
C++
#ifndef UTIL_KEY_VALUE_PACKING__
|
|
#define UTIL_KEY_VALUE_PACKING__
|
|
|
|
/* Why such a general interface? I'm planning on doing bit-level packing. */
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
|
|
#include <stdint.h>
|
|
|
|
namespace util {
|
|
|
|
template <class Key, class Value> struct Entry {
|
|
Key key;
|
|
Value value;
|
|
|
|
const Key &GetKey() const { return key; }
|
|
const Value &GetValue() const { return value; }
|
|
|
|
Value &MutableValue() { return value; }
|
|
|
|
void Set(const Key &key_in, const Value &value_in) {
|
|
SetKey(key_in);
|
|
SetValue(value_in);
|
|
}
|
|
void SetKey(const Key &key_in) { key = key_in; }
|
|
void SetValue(const Value &value_in) { value = value_in; }
|
|
|
|
bool operator<(const Entry<Key, Value> &other) const { return GetKey() < other.GetKey(); }
|
|
};
|
|
|
|
// And now for a brief interlude to specialize std::swap.
|
|
} // namespace util
|
|
namespace std {
|
|
template <class Key, class Value> void swap(util::Entry<Key, Value> &first, util::Entry<Key, Value> &second) {
|
|
swap(first.key, second.key);
|
|
swap(first.value, second.value);
|
|
}
|
|
}// namespace std
|
|
namespace util {
|
|
|
|
template <class KeyT, class ValueT> class AlignedPacking {
|
|
public:
|
|
typedef KeyT Key;
|
|
typedef ValueT Value;
|
|
|
|
public:
|
|
static const std::size_t kBytes = sizeof(Entry<Key, Value>);
|
|
static const std::size_t kBits = kBytes * 8;
|
|
|
|
typedef Entry<Key, Value> * MutableIterator;
|
|
typedef const Entry<Key, Value> * ConstIterator;
|
|
typedef const Entry<Key, Value> & ConstReference;
|
|
|
|
static MutableIterator FromVoid(void *start) {
|
|
return reinterpret_cast<MutableIterator>(start);
|
|
}
|
|
|
|
static Entry<Key, Value> Make(const Key &key, const Value &value) {
|
|
Entry<Key, Value> ret;
|
|
ret.Set(key, value);
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
template <class KeyT, class ValueT> class ByteAlignedPacking {
|
|
public:
|
|
typedef KeyT Key;
|
|
typedef ValueT Value;
|
|
|
|
private:
|
|
#pragma pack(push)
|
|
#pragma pack(1)
|
|
struct RawEntry {
|
|
Key key;
|
|
Value value;
|
|
|
|
const Key &GetKey() const { return key; }
|
|
const Value &GetValue() const { return value; }
|
|
|
|
Value &MutableValue() { return value; }
|
|
|
|
void Set(const Key &key_in, const Value &value_in) {
|
|
SetKey(key_in);
|
|
SetValue(value_in);
|
|
}
|
|
void SetKey(const Key &key_in) { key = key_in; }
|
|
void SetValue(const Value &value_in) { value = value_in; }
|
|
|
|
bool operator<(const RawEntry &other) const { return GetKey() < other.GetKey(); }
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
friend void std::swap<>(RawEntry&, RawEntry&);
|
|
|
|
public:
|
|
typedef RawEntry *MutableIterator;
|
|
typedef const RawEntry *ConstIterator;
|
|
typedef RawEntry &ConstReference;
|
|
|
|
static const std::size_t kBytes = sizeof(RawEntry);
|
|
static const std::size_t kBits = kBytes * 8;
|
|
|
|
static MutableIterator FromVoid(void *start) {
|
|
return MutableIterator(reinterpret_cast<RawEntry*>(start));
|
|
}
|
|
|
|
static RawEntry Make(const Key &key, const Value &value) {
|
|
RawEntry ret;
|
|
ret.Set(key, value);
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
} // namespace util
|
|
namespace std {
|
|
template <class Key, class Value> void swap(
|
|
typename util::ByteAlignedPacking<Key, Value>::RawEntry &first,
|
|
typename util::ByteAlignedPacking<Key, Value>::RawEntry &second) {
|
|
swap(first.key, second.key);
|
|
swap(first.value, second.value);
|
|
}
|
|
}// namespace std
|
|
|
|
#endif // UTIL_KEY_VALUE_PACKING__
|