|
Joshua
open source statistical hierarchical phrase-based machine translation system
|
00001 #ifndef UTIL_KEY_VALUE_PACKING__ 00002 #define UTIL_KEY_VALUE_PACKING__ 00003 00004 /* Why such a general interface? I'm planning on doing bit-level packing. */ 00005 00006 #include <algorithm> 00007 #include <cstddef> 00008 #include <cstring> 00009 00010 #include <inttypes.h> 00011 00012 namespace util { 00013 00014 template <class Key, class Value> struct Entry { 00015 Key key; 00016 Value value; 00017 00018 const Key &GetKey() const { return key; } 00019 const Value &GetValue() const { return value; } 00020 00021 Value &MutableValue() { return value; } 00022 00023 void Set(const Key &key_in, const Value &value_in) { 00024 SetKey(key_in); 00025 SetValue(value_in); 00026 } 00027 void SetKey(const Key &key_in) { key = key_in; } 00028 void SetValue(const Value &value_in) { value = value_in; } 00029 00030 bool operator<(const Entry<Key, Value> &other) const { return GetKey() < other.GetKey(); } 00031 }; 00032 00033 // And now for a brief interlude to specialize std::swap. 00034 } // namespace util 00035 namespace std { 00036 template <class Key, class Value> void swap(util::Entry<Key, Value> &first, util::Entry<Key, Value> &second) { 00037 swap(first.key, second.key); 00038 swap(first.value, second.value); 00039 } 00040 }// namespace std 00041 namespace util { 00042 00043 template <class KeyT, class ValueT> class AlignedPacking { 00044 public: 00045 typedef KeyT Key; 00046 typedef ValueT Value; 00047 00048 public: 00049 static const std::size_t kBytes = sizeof(Entry<Key, Value>); 00050 static const std::size_t kBits = kBytes * 8; 00051 00052 typedef Entry<Key, Value> * MutableIterator; 00053 typedef const Entry<Key, Value> * ConstIterator; 00054 typedef const Entry<Key, Value> & ConstReference; 00055 00056 static MutableIterator FromVoid(void *start) { 00057 return reinterpret_cast<MutableIterator>(start); 00058 } 00059 00060 static Entry<Key, Value> Make(const Key &key, const Value &value) { 00061 Entry<Key, Value> ret; 00062 ret.Set(key, value); 00063 return ret; 00064 } 00065 }; 00066 00067 template <class KeyT, class ValueT> class ByteAlignedPacking { 00068 public: 00069 typedef KeyT Key; 00070 typedef ValueT Value; 00071 00072 private: 00073 #pragma pack(push) 00074 #pragma pack(1) 00075 struct RawEntry { 00076 Key key; 00077 Value value; 00078 00079 const Key &GetKey() const { return key; } 00080 const Value &GetValue() const { return value; } 00081 00082 Value &MutableValue() { return value; } 00083 00084 void Set(const Key &key_in, const Value &value_in) { 00085 SetKey(key_in); 00086 SetValue(value_in); 00087 } 00088 void SetKey(const Key &key_in) { key = key_in; } 00089 void SetValue(const Value &value_in) { value = value_in; } 00090 00091 bool operator<(const RawEntry &other) const { return GetKey() < other.GetKey(); } 00092 }; 00093 #pragma pack(pop) 00094 00095 friend void std::swap<>(RawEntry&, RawEntry&); 00096 00097 public: 00098 typedef RawEntry *MutableIterator; 00099 typedef const RawEntry *ConstIterator; 00100 typedef RawEntry &ConstReference; 00101 00102 static const std::size_t kBytes = sizeof(RawEntry); 00103 static const std::size_t kBits = kBytes * 8; 00104 00105 static MutableIterator FromVoid(void *start) { 00106 return MutableIterator(reinterpret_cast<RawEntry*>(start)); 00107 } 00108 00109 static RawEntry Make(const Key &key, const Value &value) { 00110 RawEntry ret; 00111 ret.Set(key, value); 00112 return ret; 00113 } 00114 }; 00115 00116 } // namespace util 00117 namespace std { 00118 template <class Key, class Value> void swap( 00119 typename util::ByteAlignedPacking<Key, Value>::RawEntry &first, 00120 typename util::ByteAlignedPacking<Key, Value>::RawEntry &second) { 00121 swap(first.key, second.key); 00122 swap(first.value, second.value); 00123 } 00124 }// namespace std 00125 00126 #endif // UTIL_KEY_VALUE_PACKING__