#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 <inttypes.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__