Joshua
open source statistical hierarchical phrase-based machine translation system
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
src/joshua/decoder/ff/lm/kenlm/util/key_value_packing.hh
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__