00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef ADOBE_TABLE_INDEX_HPP
00010 #define ADOBE_TABLE_INDEX_HPP
00011
00012
00013
00014 #include <adobe/config.hpp>
00015
00016 #include <functional>
00017 #include <stdexcept>
00018 #include <vector>
00019
00020 #include <boost/operators.hpp>
00021 #include <boost/iterator/indirect_iterator.hpp>
00022 #include <boost/iterator/transform_iterator.hpp>
00023 #include <boost/next_prior.hpp>
00024 #include <boost/type_traits/remove_reference.hpp>
00025
00026 #include <adobe/algorithm/count.hpp>
00027 #include <adobe/algorithm/equal_range.hpp>
00028 #include <adobe/algorithm/lower_bound.hpp>
00029 #include <adobe/algorithm/sort.hpp>
00030 #include <adobe/algorithm/unique.hpp>
00031 #include <adobe/algorithm/upper_bound.hpp>
00032
00033 #include <adobe/closed_hash.hpp>
00034 #include <adobe/functional.hpp>
00035
00036
00037
00038 namespace adobe {
00039
00040
00041
00531 template < typename T,
00532 typename H = boost::hash<T>,
00533 typename C = std::equal_to<T>,
00534 typename P = identity<T> >
00535 class hash_index
00536 {
00537 public:
00538 typedef T value_type;
00539 typedef P key_function_type;
00540
00541 typedef typename boost::remove_reference<typename key_function_type::result_type>::type
00542 key_type;
00543
00544 typedef H hasher;
00545 typedef C key_equal;
00546 typedef value_type* pointer;
00547 typedef const value_type* const_pointer;
00548 typedef value_type& reference;
00549 typedef const value_type& const_reference;
00550 typedef std::size_t size_type;
00551 typedef std::ptrdiff_t difference_type;
00552
00553 typedef unary_compose< key_function_type, indirect<value_type> > indirect_key_function_type;
00554
00555 typedef closed_hash_set<pointer, indirect_key_function_type, hasher, key_equal>
00556 index_type;
00557
00558 typedef boost::indirect_iterator<typename index_type::iterator> iterator;
00559 typedef boost::indirect_iterator<typename index_type::const_iterator> const_iterator;
00560 typedef std::reverse_iterator<iterator> reverse_iterator;
00561 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00562
00563
00564
00565
00566
00567
00568
00569 hash_index() { }
00570
00571
00572
00573
00574
00575 template <typename F>
00576 hash_index(hasher hf, key_equal eq, F kf) :
00577 index_m(0, hf, eq, compose(key_function_type(kf), indirect<value_type>()))
00578 { }
00579
00580
00581 size_type max_size() const { return index_m.max_size(); }
00582
00583 size_type size() const { return index_m.size(); }
00584 bool empty() const { return index_m.empty(); }
00585 size_type capacity() const { return index_m.capacity(); }
00586
00587 void reserve(size_type n) { index_m.reserve(); }
00588
00589 iterator begin() { return iterator(index_m.begin()); }
00590 iterator end() { return iterator(index_m.end()); }
00591
00592 const_iterator begin() const { return const_iterator(index_m.begin()); }
00593 const_iterator end() const { return const_iterator(index_m.end()); }
00594
00595 reverse_iterator rbegin() { return reverse_iterator(index_m.rbegin()); }
00596 reverse_iterator rend() { return reverse_iterator(index_m.rend()); }
00597
00598 const_reverse_iterator rbegin() const { return const_reverse_iterator(index_m.rbegin()); }
00599 const_reverse_iterator rend() const { return const_reverse_iterator(index_m.rend()); }
00600
00601 std::pair<iterator, bool> insert(value_type& x)
00602 {
00603 std::pair<typename index_type::iterator, bool> result = index_m.insert(&x);
00604 return std::make_pair(iterator(result.first), result.second);
00605 }
00606
00607 template <typename I>
00608 void insert(I f, I l)
00609 {
00610 index_m.insert( boost::make_transform_iterator(f, pointer_to<value_type>()),
00611 boost::make_transform_iterator(l, pointer_to<value_type>()));
00612 }
00613
00614 iterator insert(iterator i, value_type& x)
00615 {
00616 return iterator(index_m.insert(i, &x));
00617 }
00618
00619 iterator erase(iterator i) { return index_m.erase(i.base()); }
00620 size_type erase(const key_type& x) { return index_m.erase(x); }
00621
00622 void clear() { index_m.clear(); }
00623
00624 index_type& index() { return index_m; }
00625 const index_type& index() const { return index_m; }
00626
00627 iterator find(const key_type& x) { return iterator(index_m.find(x)); }
00628 const_iterator find(const key_type& x) const { return const_iterator(index_m.find(x)); }
00629 size_type count(const key_type& x) const { return index_m.count(x); }
00630
00631 iterator lower_bound(const key_type& x) { return iterator(index_m.lower_bound()); }
00632 const_iterator lower_bound(const key_type& x) const
00633 { return const_iterator(index_m.lower_bound()); }
00634 iterator upper_bound(const key_type& x) { return iterator(index_m.upper_bound()); }
00635 const_iterator upper_bound(const key_type& x) const
00636 { return const_iterator(index_m.upper_bound()); }
00637
00638 std::pair<iterator, iterator> equal_range(const key_type& x)
00639 {
00640 std::pair<typename index_type::iterator, typename index_type::iterator> result = index_m.equal_range(x);
00641 return std::make_pair(iterator(result.first), iterator(result.second));
00642 }
00643 std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
00644 {
00645 std::pair<typename index_type::const_iterator, typename index_type::const_iterator> result
00646 = index_m.equal_range(x);
00647
00648 return std::make_pair(const_iterator(result.first), const_iterator(result.second));
00649 }
00650
00651 key_function_type key_function() const { return index_m.key_function(); }
00652 hasher hash_function() const { return index_m.hash_function(); }
00653 key_equal key_eq() const { return index_m.key_eq(); }
00654
00655 friend void swap(hash_index& x, hash_index& y)
00656 {
00657 swap(x.index_m, y.index_m);
00658 }
00659 private:
00660
00661 index_type index_m;
00662 };
00663
00664
00665
00666 template < typename Key,
00667 typename T,
00668 typename Transform = mem_data_t<T, const Key>,
00669 typename Compare = std::less<Key>
00670 >
00671 class table_index
00672 {
00673
00674 public:
00675 typedef typename std::vector<T*> index_type;
00676 typedef Transform transform_type;
00677
00678 typedef Key key_type;
00679 typedef T value_type;
00680 typedef Compare key_compare;
00681
00682 typedef T& reference;
00683 typedef const T& const_reference;
00684 typedef typename index_type::size_type size_type;
00685 typedef typename index_type::difference_type difference_type;
00686 typedef T* pointer;
00687 typedef const T* const_pointer;
00688
00689 typedef boost::indirect_iterator<typename index_type::iterator> iterator;
00690 typedef boost::indirect_iterator<typename index_type::const_iterator> const_iterator;
00691 typedef std::reverse_iterator<iterator> reverse_iterator;
00692 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00693
00694 template <class TransformPrimitive>
00695 explicit table_index(TransformPrimitive transform, const key_compare& compare = key_compare()) :
00696 transform_m(transform),
00697 compare_m(compare)
00698 { }
00699 explicit table_index(const transform_type&, const key_compare& = key_compare());
00700
00701 template <typename InputIterator, typename TransformPrimitive>
00702 table_index( InputIterator first,
00703 InputIterator last,
00704 TransformPrimitive transform,
00705 const key_compare& compare = key_compare()) :
00706 transform_m(transform),
00707 compare_m(compare)
00708 {
00709 insert(begin(), first, last);
00710 }
00711
00712
00713 size_type max_size() const;
00714
00715 size_type size() const;
00716 bool empty() const;
00717
00718 iterator begin();
00719 const_iterator begin() const;
00720 iterator end();
00721 const_iterator end() const;
00722
00723 reverse_iterator rbegin();
00724 const_reverse_iterator rbegin() const;
00725 reverse_iterator rend();
00726 const_reverse_iterator rend() const;
00727
00728 const_reference at(size_type n) const;
00729 reference at(size_type n);
00730
00731 reference front();
00732 const_reference front() const;
00733 reference back();
00734 const_reference back() const;
00735
00736 void push_back(value_type&);
00737 void pop_back();
00738
00739 iterator insert(iterator, value_type&);
00740 template <class InputIterator>
00741 void insert(iterator position, InputIterator first, InputIterator last);
00742
00743 iterator erase(iterator location);
00744 iterator erase(iterator first, iterator last);
00745 void clear();
00746
00747 index_type& index();
00748 const index_type& index() const;
00749
00750
00751
00752
00753
00754
00755
00756 void sort();
00757
00758
00759
00760 void unique();
00761
00762 reference operator[](const key_type&);
00763 const_reference operator[](const key_type&) const;
00764
00765 iterator find(const key_type& x);
00766 const_iterator find(const key_type& x) const;
00767 size_type count(const key_type& x) const;
00768
00769 iterator lower_bound(const key_type& x);
00770 const_iterator lower_bound(const key_type& x) const;
00771 iterator upper_bound(const key_type& x);
00772 const_iterator upper_bound(const key_type& x) const;
00773
00774 std::pair<iterator, iterator> equal_range(const key_type& x);
00775 std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
00776
00777 transform_type transform() const { return transform_m; }
00778
00779 friend void swap(table_index& x, table_index& y)
00780 {
00781 swap(x.transform_m, y.transform_m);
00782 swap(x.compare_m, y.compare_m);
00783 swap(x.index_m, y.index_m);
00784 }
00785 private:
00786
00787 #ifndef ADOBE_NO_DOCUMENTATION
00788 struct indirect_compare_t : std::binary_function<pointer, pointer, bool>
00789 {
00790 typedef bool result_type;
00791
00792 indirect_compare_t(transform_type& transform, const key_compare& compare) :
00793 transform_m(transform),
00794 compare_m(compare)
00795 { }
00796
00797 bool operator () (pointer x, pointer y) const
00798 {
00799 return compare_m(transform_m(*x), transform_m(*y));
00800 }
00801
00802 private:
00803 transform_type transform_m;
00804 key_compare compare_m;
00805 };
00806
00807 #endif
00808
00809 transform_type transform_m;
00810 key_compare compare_m;
00811 index_type index_m;
00812 };
00813
00814
00815
00816 template <class Key, class T, class Compare, class Transform>
00817 table_index<Key, T, Compare, Transform>::table_index( const transform_type& transform,
00818 const key_compare& compare) :
00819 transform_m(transform),
00820 compare_m(compare)
00821 { }
00822
00823
00824
00825 template <class Key, class T, class Compare, class Transform>
00826 inline typename table_index<Key, T, Compare, Transform>::iterator
00827 table_index<Key, T, Compare, Transform>::begin()
00828 {
00829 return iterator(index_m.begin());
00830 }
00831
00832
00833
00834 template <class Key, class T, class Compare, class Transform>
00835 inline typename table_index<Key, T, Compare, Transform>::const_iterator
00836 table_index<Key, T, Compare, Transform>::begin() const
00837 {
00838 return const_iterator(index_m.begin());
00839 }
00840
00841
00842
00843 template <class Key, class T, class Compare, class Transform>
00844 inline typename table_index<Key, T, Compare, Transform>::iterator
00845 table_index<Key, T, Compare, Transform>::end()
00846 {
00847 return iterator(index_m.end());
00848 }
00849
00850
00851
00852 template <class Key, class T, class Compare, class Transform>
00853 inline typename table_index<Key, T, Compare, Transform>::const_iterator
00854 table_index<Key, T, Compare, Transform>::end() const
00855 {
00856 return const_iterator(index_m.end());
00857 }
00858
00859
00860
00861 template <class Key, class T, class Compare, class Transform>
00862 inline typename table_index<Key, T, Compare, Transform>::reverse_iterator
00863 table_index<Key, T, Compare, Transform>::rbegin()
00864 {
00865 return reverse_iterator(index_m.rbegin());
00866 }
00867
00868
00869
00870 template <class Key, class T, class Compare, class Transform>
00871 inline typename table_index<Key, T, Compare, Transform>::const_reverse_iterator
00872 table_index<Key, T, Compare, Transform>::rbegin() const
00873 {
00874 return const_reverse_iterator(index_m.rbegin());
00875 }
00876
00877
00878
00879 template <class Key, class T, class Compare, class Transform>
00880 inline typename table_index<Key, T, Compare, Transform>::reverse_iterator
00881 table_index<Key, T, Compare, Transform>::rend()
00882 {
00883 return reverse_iterator(index_m.rend());
00884 }
00885
00886
00887
00888 template <class Key, class T, class Compare, class Transform>
00889 inline typename table_index<Key, T, Compare, Transform>::const_reverse_iterator
00890 table_index<Key, T, Compare, Transform>::rend() const
00891 {
00892 return reverse_iterator(index_m.rend());
00893 }
00894
00895
00896
00897 template <class Key, class T, class Compare, class Transform>
00898 inline typename table_index<Key, T, Compare, Transform>::size_type
00899 table_index<Key, T, Compare, Transform>::max_size() const
00900 {
00901 return index_m.max_size();
00902 }
00903
00904
00905
00906 template <class Key, class T, class Compare, class Transform>
00907 inline typename table_index<Key, T, Compare, Transform>::size_type
00908 table_index<Key, T, Compare, Transform>::size() const
00909 {
00910 return index_m.size();
00911 }
00912
00913
00914
00915 template <class Key, class T, class Compare, class Transform>
00916 inline bool table_index<Key, T, Compare, Transform>::empty() const
00917 {
00918 return index_m.empty();
00919 }
00920
00921
00922
00923 template <class Key, class T, class Compare, class Transform>
00924 inline void table_index<Key, T, Compare, Transform>::push_back(value_type& x)
00925 {
00926 index_m.push_back(&x);
00927 }
00928
00929
00930
00931 template <class Key, class T, class Compare, class Transform>
00932 inline void table_index<Key, T, Compare, Transform>::pop_back()
00933 {
00934 index_m.pop_back();
00935 }
00936
00937
00938
00939 template <class Key, class T, class Compare, class Transform>
00940 inline typename table_index<Key, T, Compare, Transform>::iterator
00941 table_index<Key, T, Compare, Transform>::insert(iterator position, value_type& x)
00942 {
00943 return index_m.insert(position, &x);
00944 }
00945
00946
00947
00948
00949
00950
00951
00952
00953 template <class Key, class T, class Compare, class Transform>
00954 template <class InputIterator>
00955 inline void table_index<Key, T, Compare, Transform>::insert(iterator position, InputIterator first, InputIterator last)
00956 {
00957 typename index_type::iterator iter = position.base();
00958
00959 while (first != last) {
00960 iter = index_m.insert(iter, &*first);
00961 ++iter;
00962 ++first;
00963 }
00964 }
00965
00966
00967
00968 template <class Key, class T, class Compare, class Transform>
00969 inline typename table_index<Key, T, Compare, Transform>::iterator
00970 table_index<Key, T, Compare, Transform>::erase(iterator position)
00971 {
00972 return index_m.erase(position.base());
00973 }
00974
00975
00976
00977 template <class Key, class T, class Compare, class Transform>
00978 inline typename table_index<Key, T, Compare, Transform>::iterator
00979 table_index<Key, T, Compare, Transform>::erase(iterator first, iterator last)
00980 {
00981 return index_m.erase(first.base(), last.base());
00982 }
00983
00984
00985
00986 template <class Key, class T, class Compare, class Transform>
00987 inline void table_index<Key, T, Compare, Transform>::clear()
00988 {
00989 index_m.clear();
00990 }
00991
00992
00993
00994 template <class Key, class T, class Compare, class Transform>
00995 void table_index<Key, T, Compare, Transform>::sort()
00996 {
00997 adobe::sort(index_m, indirect_compare_t(transform_m, compare_m));
00998 }
00999
01000
01001
01002 template <class Key, class T, class Compare, class Transform>
01003 void table_index<Key, T, Compare, Transform>::unique()
01004 {
01005 typename index_type::iterator i (adobe::unique(index_m, indirect_compare_t(transform_m, compare_m)));
01006 index_m.erase(i, index_m.end());
01007 }
01008
01009
01010
01011 template <class Key, class T, class Compare, class Transform>
01012 inline typename table_index<Key, T, Compare, Transform>::reference
01013 table_index<Key, T, Compare, Transform>::at(const size_type n)
01014 {
01015 return *index_m.at(n);
01016 }
01017
01018
01019
01020 template <class Key, class T, class Compare, class Transform>
01021 inline typename table_index<Key, T, Compare, Transform>::const_reference
01022 table_index<Key, T, Compare, Transform>::at(const size_type n) const
01023 {
01024 return *index_m.at(n);
01025 }
01026
01027
01028
01029 template <class Key, class T, class Compare, class Transform>
01030 inline typename table_index<Key, T, Compare, Transform>::reference
01031 table_index<Key, T, Compare, Transform>::operator [] (const key_type& key)
01032 {
01033 iterator iter (find(key));
01034
01035 if (iter == end())
01036 throw std::range_error("Key not present in table.");
01037
01038 return *iter;
01039 }
01040
01041
01042
01043 template <class Key, class T, class Compare, class Transform>
01044 inline typename table_index<Key, T, Compare, Transform>::const_reference
01045 table_index<Key, T, Compare, Transform>::operator [] (const key_type& key) const
01046 {
01047 const_iterator iter(find(key));
01048
01049 if (iter == end())
01050 throw std::range_error("Key not present in table.");
01051
01052 return *iter;
01053 }
01054
01055
01056
01057 template <class Key, class T, class Compare, class Transform>
01058 inline typename table_index<Key, T, Compare, Transform>::iterator
01059 table_index<Key, T, Compare, Transform>::find(const key_type& key)
01060 {
01061 typename index_type::iterator iter = lower_bound(key).base();
01062
01063 if (iter != index_m.end() && transform_m(**iter) != key)
01064 iter = index_m.end();
01065
01066 return iter;
01067 }
01068
01069
01070
01071 template <class Key, class T, class Compare, class Transform>
01072 inline typename table_index<Key, T, Compare, Transform>::const_iterator
01073 table_index<Key, T, Compare, Transform>::find(const key_type& key) const
01074 {
01075 typename index_type::const_iterator iter = lower_bound(key).base();
01076
01077 if (iter != index_m.end() && transform_m(**iter) != key)
01078 iter = index_m.end();
01079
01080 return iter;
01081 }
01082
01083
01084
01085 template <class Key, class T, class Compare, class Transform>
01086 inline typename table_index<Key, T, Compare, Transform>::size_type
01087 table_index<Key, T, Compare, Transform>::count(const key_type& key) const
01088 {
01089 return adobe::count_if(index_m, bound_predicate_t(key, transform_m, compare_m));
01090 }
01091
01092
01093
01094 template <class Key, class T, class Compare, class Transform>
01095 inline typename table_index<Key, T, Compare, Transform>::iterator
01096 table_index<Key, T, Compare, Transform>::lower_bound(const key_type& key)
01097 {
01098 return adobe::lower_bound(index_m, key, compare_m,
01099 boost::bind(transform_m, bind(indirect<value_type>(), _1)));
01100 }
01101
01102
01103
01104 template <class Key, class T, class Compare, class Transform>
01105 inline typename table_index<Key, T, Compare, Transform>::const_iterator
01106 table_index<Key, T, Compare, Transform>::lower_bound(const key_type& key) const
01107 {
01108 return adobe::lower_bound(index_m, key, compare_m,
01109 boost::bind(transform_m, bind(indirect<value_type>(), _1)));
01110 }
01111
01112
01113
01114 template <class Key, class T, class Compare, class Transform>
01115 inline typename table_index<Key, T, Compare, Transform>::iterator
01116 table_index<Key, T, Compare, Transform>::upper_bound(const key_type& key)
01117 {
01118 return adobe::upper_bound(index_m, key, compare_m,
01119 boost::bind(transform_m, bind(indirect<value_type>(), _1)));
01120 }
01121
01122
01123
01124 template <class Key, class T, class Compare, class Transform>
01125 inline typename table_index<Key, T, Compare, Transform>::const_iterator
01126 table_index<Key, T, Compare, Transform>::upper_bound(const key_type& key) const
01127 {
01128 return adobe::upper_bound(index_m, key, compare_m,
01129 boost::bind(transform_m, bind(indirect<value_type>(), _1)));
01130 }
01131
01132
01133
01134 template <class Key, class T, class Compare, class Transform>
01135 inline std::pair< typename table_index<Key, T, Compare, Transform>::iterator,
01136 typename table_index<Key, T, Compare, Transform>::iterator>
01137 table_index<Key, T, Compare, Transform>::equal_range(const key_type& key)
01138 {
01139 return adobe::equal_range(index_m, key, compare_m,
01140 boost::bind(transform_m, bind(indirect<value_type>(), _1)));
01141 }
01142
01143
01144
01145 template <class Key, class T, class Compare, class Transform>
01146 inline std::pair< typename table_index<Key, T, Compare, Transform>::const_iterator,
01147 typename table_index<Key, T, Compare, Transform>::const_iterator>
01148 table_index<Key, T, Compare, Transform>::equal_range(const key_type& key) const
01149 {
01150 return adobe::equal_range(index_m, key, compare_m,
01151 boost::bind(transform_m, bind(indirect<value_type>(), _1)));
01152 }
01153
01154
01155
01156 template <class Key, class T, class Compare, class Transform>
01157 inline typename table_index<Key, T, Compare, Transform>::index_type&
01158 table_index<Key, T, Compare, Transform>::index()
01159 {
01160 return index_m;
01161 }
01162
01163
01164
01165 template <class Key, class T, class Compare, class Transform>
01166 inline const typename table_index<Key, T, Compare, Transform>::index_type&
01167 table_index<Key, T, Compare, Transform>::index() const
01168 {
01169 return index_m;
01170 }
01171
01172
01173
01174 }
01175
01176
01177
01178 #endif
01179
01180