#ifndef UTIL_KEY_VALUE_PACKING__ #define UTIL_KEY_VALUE_PACKING__ /* Why such a general interface? I'm planning on doing bit-level packing. */ #include #include #include #include namespace util { template 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 &other) const { return GetKey() < other.GetKey(); } }; // And now for a brief interlude to specialize std::swap. } // namespace util namespace std { template void swap(util::Entry &first, util::Entry &second) { swap(first.key, second.key); swap(first.value, second.value); } }// namespace std namespace util { template class AlignedPacking { public: typedef KeyT Key; typedef ValueT Value; public: static const std::size_t kBytes = sizeof(Entry); static const std::size_t kBits = kBytes * 8; typedef Entry * MutableIterator; typedef const Entry * ConstIterator; typedef const Entry & ConstReference; static MutableIterator FromVoid(void *start) { return reinterpret_cast(start); } static Entry Make(const Key &key, const Value &value) { Entry ret; ret.Set(key, value); return ret; } }; template 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(start)); } static RawEntry Make(const Key &key, const Value &value) { RawEntry ret; ret.Set(key, value); return ret; } }; } // namespace util namespace std { template void swap( typename util::ByteAlignedPacking::RawEntry &first, typename util::ByteAlignedPacking::RawEntry &second) { swap(first.key, second.key); swap(first.value, second.value); } }// namespace std #endif // UTIL_KEY_VALUE_PACKING__