summaryrefslogtreecommitdiff
path: root/klm/util/sized_iterator.hh
blob: dce8f229a26975c5b6124b86b9ea0be3948323b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef UTIL_SIZED_ITERATOR__
#define UTIL_SIZED_ITERATOR__

#include "util/proxy_iterator.hh"

#include <algorithm>
#include <functional>
#include <string>

#include <stdint.h>
#include <string.h>

namespace util {

class SizedInnerIterator {
  public:
    SizedInnerIterator() {}

    SizedInnerIterator(void *ptr, std::size_t size) : ptr_(static_cast<uint8_t*>(ptr)), size_(size) {}

    bool operator==(const SizedInnerIterator &other) const {
      return ptr_ == other.ptr_;
    }
    bool operator<(const SizedInnerIterator &other) const {
      return ptr_ < other.ptr_;
    }
    SizedInnerIterator &operator+=(std::ptrdiff_t amount) {
      ptr_ += amount * size_;
      return *this;
    }
    std::ptrdiff_t operator-(const SizedInnerIterator &other) const {
      return (ptr_ - other.ptr_) / size_;
    }

    const void *Data() const { return ptr_; }
    void *Data() { return ptr_; }
    std::size_t EntrySize() const { return size_; }

    friend inline void swap(SizedInnerIterator &first, SizedInnerIterator &second) {
      std::swap(first.ptr_, second.ptr_);
      std::swap(first.size_, second.size_);
    }

  private:
    uint8_t *ptr_;
    std::size_t size_;
};

class SizedProxy {
  public:
    SizedProxy() {}

    SizedProxy(void *ptr, std::size_t size) : inner_(ptr, size) {}

    operator std::string() const {
      return std::string(reinterpret_cast<const char*>(inner_.Data()), inner_.EntrySize());
    }

    SizedProxy &operator=(const SizedProxy &from) {
      memcpy(inner_.Data(), from.inner_.Data(), inner_.EntrySize());
      return *this;
    }

    SizedProxy &operator=(const std::string &from) {
      memcpy(inner_.Data(), from.data(), inner_.EntrySize());
      return *this;
    }

    const void *Data() const { return inner_.Data(); }
    void *Data() { return inner_.Data(); }

  /**
     // TODO: this (deep) swap was recently added. why? if any std heap sort etc
     // algs are using swap, that's going to be worse performance than using
     // =. i'm not sure why we *want* a deep swap. if C++11 compilers are
     // choosing between move constructor and swap, then we'd better implement a
     // (deep) move constructor. it may also be that this is moot since i made
     // ProxyIterator a reference and added a shallow ProxyIterator swap? (I
     // need Ken or someone competent to judge whether that's correct also. -
     // let me know at graehl@gmail.com
  */
    friend void swap(SizedProxy &first, SizedProxy &second) {
      std::swap_ranges(
          static_cast<char*>(first.inner_.Data()),
          static_cast<char*>(first.inner_.Data()) + first.inner_.EntrySize(),
          static_cast<char*>(second.inner_.Data()));
    }

  private:
    friend class util::ProxyIterator<SizedProxy>;

    typedef std::string value_type;

    typedef SizedInnerIterator InnerIterator;

    InnerIterator &Inner() { return inner_; }
    const InnerIterator &Inner() const { return inner_; }
    InnerIterator inner_;
};

typedef ProxyIterator<SizedProxy> SizedIterator;

inline SizedIterator SizedIt(void *ptr, std::size_t size) { return SizedIterator(SizedProxy(ptr, size)); }

// Useful wrapper for a comparison function i.e. sort.
template <class Delegate, class Proxy = SizedProxy> class SizedCompare : public std::binary_function<const Proxy &, const Proxy &, bool> {
  public:
    explicit SizedCompare(const Delegate &delegate = Delegate()) : delegate_(delegate) {}

    bool operator()(const Proxy &first, const Proxy &second) const {
      return delegate_(first.Data(), second.Data());
    }
    bool operator()(const Proxy &first, const std::string &second) const {
      return delegate_(first.Data(), second.data());
    }
    bool operator()(const std::string &first, const Proxy &second) const {
      return delegate_(first.data(), second.Data());
    }
    bool operator()(const std::string &first, const std::string &second) const {
      return delegate_(first.data(), second.data());
    }

    const Delegate &GetDelegate() const { return delegate_; }

  private:
    const Delegate delegate_;
};

} // namespace util
#endif // UTIL_SIZED_ITERATOR__