#ifndef UTIL_SIZED_ITERATOR__ #define UTIL_SIZED_ITERATOR__ #include "util/proxy_iterator.hh" #include #include #include #include #include namespace util { class SizedInnerIterator { public: SizedInnerIterator() {} SizedInnerIterator(void *ptr, std::size_t size) : ptr_(static_cast(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(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(first.inner_.Data()), static_cast(first.inner_.Data()) + first.inner_.EntrySize(), static_cast(second.inner_.Data())); } private: friend class util::ProxyIterator; typedef std::string value_type; typedef SizedInnerIterator InnerIterator; InnerIterator &Inner() { return inner_; } const InnerIterator &Inner() const { return inner_; } InnerIterator inner_; }; typedef ProxyIterator 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 SizedCompare : public std::binary_function { 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__